| 
 
 |   | 
Object. 
    
class stack
  void push(Object o) { ... }
  Object pop() { ... }
Stack stk = new Stack()
stk.push("hello")
String str = (String) stk.pop()
stk.push(1) String str = (String) stk.pop()
Stack stk = new Stack() stk.push(new Spot()) Drip drip = (Drip) stk.pop() // boom!
class StringStack
  void push(String str) { ... }
  String pop() { ... }
class DripStack
  void push(Drip drip) { ... }
  Drip pop() { ... }
// and so on.
T is a type variable.
class TStack
  void push(T t) { ... }
  T pop() {...}
TypeVariable T = String
TStack stringStk = new TStack()
stringStk.push("hello")
String str = stringStk.pop()
T = Drip
TStack dripStk = new TStack()
dripStk.push(new Drip())
Drip drip = dripStk.pop()
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() { ... }
newnew.
class Stack<T> private final int max = 10 private T elements[] =new T[max]
class Stack<T>
  private final int max = 10
  private Object stk[] = new Object[max]
  T pop() { return (T) stk[--top] }
staticclass SharedMailbox<T> privatestatic Tslot = null publicstatic TpickUp() { return slot } public static deliver(T t) { slot = t }
Stack<int> intStack = new Stack<int>()
Stack<Integer> integerStack = new Stack<Integer>() integerStack.push(1) int i = integerStack.pop()
class Mailbox<T>
  private T slot
  void put(T t) { slot = t }
  T get() { return slot }
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 slot } 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 slot } 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 slot }
Mailbox mailBox = 
  new Mailbox()
mailBox.put(new Letter())
Letter letter = (Letter) mailBox.get()
Ta da! No generics.
new.
class MailBox<T> // Start with a default letter. private T mailBox =new T()
newT is replaced by Object, which isn’t useful.
class MailBox // Start with a default letter. private Object mailBox = new Object()
Stack<int> intStack = new Stack<int>()
Why not?
T by it’s most distant ancestor.
    
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. 
    
