3-minute skim. Full detail → Generics — Full Notes.
The 8 facts
- Generics = compile-time type safety; erased at runtime.
- Invariant:
List<Integer>is NOT aList<Number>. <?>= unknown, read-only as Object.<? extends T>= T or subtype → READ (producer). Can’t add.<? super T>= T or supertype → WRITE (consumer). Read back as Object.- PECS — Producer Extends, Consumer Super.
- Type erasure ⇒ no
new T[], noinstanceof List<String>, no generic-only overloads. - Type parameters use
extendsonly (upper bound) — nosuperfor type params;superis wildcards only.
Signatures to recognize
Collections.copy(List<? super T> dest, List<? extends T> src)— PECS in the JDK.<T extends Comparable<T>> T max(List<T>)— bounded type parameter.<T extends Number & Comparable<T>>— multiple bounds.
Drill cards
PECS — what is it?::Producer Extends, Consumer Super. Read from ? extends T; write to ? super T.
Why can’t you add to List<? extends Number>?::Compiler only knows it’s some subtype; adding could corrupt (e.g. a Double into a List
What is type erasure?::Generics are removed at runtime (List
Are generics covariant like arrays?::No — generics are invariant (List
extends vs super — where does each apply?::Type parameters: extends (upper bound) only. Wildcards: both ? extends (read) and ? super (write).