24. Generics and Type Erasure
Generics provide compile-time type safety; type erasure removes generic type information at runtime. A List<String> is just a List in bytecode โ causing instanceof limits and unchecked cast warnings.
Explanation
Generics are a compile-time feature. The compiler inserts type checks and casts where needed, then erases the type parameters โ the bytecode for List<String> and List<Integer> is identical: plain List. This design kept generics backwards-compatible with pre-Java-5 code.
Consequences of type erasure: you cannot use instanceof with parameterised types (obj instanceof List<String> is a compile error; only obj instanceof List<?> is allowed). You cannot create generic arrays (new T[] fails). Static fields/methods cannot reference class type parameters.
Raw types (List without <>) bypass all generic checking and exist only for backwards compatibility โ never use them in new code. The diamond operator (<>) (Java 7+) lets the compiler infer type arguments: new ArrayList<>().
Example
import java.util.ArrayList;
import java.util.List;
public class GenericsTypeErasure {
// Generic method
static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
// Generic class
static class Box<T> {
private T value;
Box(T value) { this.value = value; }
T get() { return value; }
@Override public String toString() { return "Box[" + value + "]"; }
}
public static void main(String[] args) {
// Compile-time type safety
List<String> strings = new ArrayList<>();
strings.add("Hello");
// strings.add(42); // compile error โ caught at compile time
// Type erasure at runtime: List<String> is just List in bytecode
Object obj = strings;
// obj instanceof List<String> โ compile error!
System.out.println(obj instanceof List<?>); // true (wildcard OK)
// Unchecked cast warning (dangerous, but compiles)
@SuppressWarnings("unchecked")
List<Integer> ints = (List<Integer>) obj; // erased to same List type
// ints.get(0) would throw ClassCastException at runtime (hidden cast)
// Diamond operator
Box<String> box = new Box<>("Java 21");
System.out.println(box);
// Generic method
System.out.println(max("apple", "banana")); // "banana"
System.out.println(max(3, 7)); // 7
// Raw type (avoid!)
@SuppressWarnings("rawtypes")
List raw = new ArrayList();
raw.add("anything"); // no warning โ unsafe
}
}Sources
- https://docs.oracle.com/javase/tutorial/java/generics/erasure.html โ Type erasure tutorial
- https://docs.oracle.com/javase/tutorial/extra/generics/index.html โ Generics tutorial