Metadata Card
- Difficulty: (Novice Village 4-star)
- Prerequisites: Ch7 (OOP), Ch10 (Core Collections)
- Core concepts: 7 (Generic classes/interfaces/methods, type erasure, wildcards ? extends/? super, bounded type parameters, generics vs arrays, type safety, bridge methods)
- Estimated time: 5-8 hrs
The Breakthrough · Tracing the Origins
You keep writing new container classes for each use case — StringBox, IntegerBox. Master Chen asks: "Can't you write one generic container and let them tell you what type to put in?"
Generic Classes
public class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}
// Usage
Box<String> stringBox = new Box<>();
stringBox.set("Hammer");
String tool = stringBox.get(); // No cast needed!T = type parameter — like a method parameter for types.
Generic Methods
public class Utils {
public static <T> T pickRandom(T[] array) {
int index = new Random().nextInt(array.length);
return array[index];
}
}Type Erasure
The most important insight about generics: They're a compile-time illusion.
Box<String> stringBox = new Box<>();
Box<Integer> integerBox = new Box<>();
System.out.println(stringBox.getClass() == integerBox.getClass()); // true!Both are just Box at runtime. The compiler checks type safety, then erases the type info.
Consequences of erasure:
- Can't
new T()— no constructor info - Can't
instanceof Box<String>— all looks likeBox - Bridge methods are generated by the compiler
Wildcards
? extends T — read-safe, write-limited:
List<? extends Number> list = new ArrayList<Integer>();
Number n = list.get(0); // OK
list.add(42); // Compile error!? super T — write-safe, read-limited:
List<? super Integer> list = new ArrayList<Number>();
list.add(42); // OK
Object obj = list.get(0); // Only Object guaranteedPECS Principle: Producer Extends, Consumer Super.
Bounded Type Parameters
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}Generics and Arrays
Arrays are covariant (String[] is Object[]). Generics are invariant (List<String> is NOT List<Object>). These conflict — you can't create new ArrayList<String>[10].
Final Challenge: Write a Stack<T> class. Implement Pair<K,V> and a utility to swap them. Build a type-safe heterogeneous container using Class<T> as key.
Traveler's Notes
Generics are compile-time safety checks — runtime erasure makes them invisible.
Can't:new T(),instanceof T,new T[].? extends= readable, not writable.? super= writable, readable as Object — remember PECS.
Arrays covariant, generics invariant — they don't mix.