class Stack<T> { ... }
class Map<K, V> { ... }
Stack<Blob> blobStack = new Stack<Blob>()
Stack” with no type variables is a valid class name.
import utils.Stack;
Class Stack<T>
private T top = null
private ArrayList<T> elts =
new ArrayList<T>()
void push(T t) { ... }
T pop() { ... }
class Mailbox<T>
private T slot
void put(T t) { slot = t }
T get() { return t }
Mailbox<Letter> mailBox =
new Mailbox<Letter>()
mailBox.put(new Letter())
Letter letter = mailBox.get()
Step 1: erase type-variable declarations
class Mailbox<T> private T slot void put(T t) { slot = t } T get() { return t } Mailbox<Letter> mailBox = new Mailbox<Letter>() mailBox.put(new Letter()) Letter letter = mailBox.get()
Step 2: Replace type variables with their most general (most ancestral) type.
class Mailbox private T Object slot void put(T Object t) { slot = t } T Object get() { return t } Mailbox mailBox = new Mailbox() mailBox.put(new Letter()) Letter letter = mailBox.get()
Step 3: Cast to maintain type correctness.
class Mailbox
private Object slot
void put(Object t) { slot = t }
Object get() { return t }
Mailbox mailBox =
new Mailbox()
mailBox.put(new Letter())
Letter letter = (Letter) mailBox.get()
Ta da! No generics.
newnew.
$ cat MailBox.java
class MailBox<T> {
private T mailBox = new T();
}
$ javac -Xlint MailBox.java
MailBox.java:2: unexpected type
found : type parameter T
required: class
private T mailBox = new T();
^
1 error
$
$ cat MailBox.java
class MailBox<T> { /* blah blah blah */ }
class test { private MailBox<int> mailBox = new MailBox<int>(); }
$ javac -Xlint MailBox.java
MailBox.java:6: unexpected type
found : int
required: reference
private MailBox<int> mailBox = new MailBox<int>();
^
MailBox.java:6: unexpected type
found : int
required: reference
private MailBox<int> mailBox = new MailBox<int>();
^
2 errors
$
static$ cat MailBox.java
import java.util.ArrayList;
class MailBox<T> {
static private T mailBoxs = new ArrayList<T>();
}
$ javac -Xlint MailBox.java
MailBox.java:4: non-static class T cannot be referenced from a static context
static private T mailBoxs = new ArrayList<T>();
^
MailBox.java:4: non-static class T cannot be referenced from a static context
static private T mailBoxs = new ArrayList<T>();
^
2 errors
$
public class
MailBox<T extends Number> {
public void
copy(MailBox<T extends Integer> v) {
// blah blah blah
}
// blah blah blah
}
class Blob { ... }
class Spot extends Blob { ... }
Mailbox<Spot> spotBox = new Mailbox<Spot>
Mailbox<Blob> blobBox = spotBox // ???
Mailbox.
Mailbox<Spot> spotBox = new Mailbox<Spot> Mailbox<Blob> blobBox = spotBox // ???
So the assignment should be fine and dandy.
class Blob { ... }
class Spot extends Blob { ... }
Mailbox<Spot> spotBox = new Mailbox<Spot>
Mailbox<Blob> blobBox = spotBox
blobBox.put(new Blob)
Spot spot = spotBox.get() // boom!
spotBox as blobBox can lead to run-time casting
exceptions, violating the generic guarantee.


any generic variant of class C type incompatible with every different generic variant of C.
void lock(Mailbox<Object> mb) { ... }
do it?
void lock(Mailbox<Object> mb) { ... }
only accepts mailboxes containing Object instances.
? indicates that
void lock(Mailbox<?> mb) { ... }
does what we want, as long as lock() doesn’t try to write polymorphic
references into mb.
Object instances.
void lock(Mailbox<?> mb) Object o = mb.get() // Ok
void lock(Mailbox<?> mb)
mb.put(new Blob()) // Compile-time error
mb.setOwner("Trollope") // Ok

void lock(Mailbox<Blob> mb) { ... }
doesn’t go far enough and this
void lock(Mailbox<?> mb) { ... }
goes too far.
extends keyword:
void lock(Mailbox<? extends Blob> mb) {…}
void lock(Mailbox<? extends Blob> mb) Blob blob = mb.get() // Ok
class Mailbox<T extends Letter> { ... }
T’s most general (ancestral) type is Letter.

class Mailbox<
T extends Letter & Refundable> { ... }
T must satisfy (extend or implement) all bounds.

| This page last modified on 22 September 2010. |