Skip to content

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

java
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

java
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.

java
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 like Box
  • Bridge methods are generated by the compiler

Wildcards

? extends T — read-safe, write-limited:

java
List<? extends Number> list = new ArrayList<Integer>();
Number n = list.get(0); // OK
list.add(42); // Compile error!

? super T — write-safe, read-limited:

java
List<? super Integer> list = new ArrayList<Number>();
list.add(42); // OK
Object obj = list.get(0); // Only Object guaranteed

PECS Principle: Producer Extends, Consumer Super.

Bounded Type Parameters

java
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.

Built with VitePress | Software Systems Atlas