Mastery
Mastery/Java/B. Generics
T1 · high-leverage

Generics are erased at runtime

Java generics exist only at compile time for type checking; the compiler erases them to raw types (and inserts casts) in the bytecode. List<String> and List<Integer> are literally the same class object at runtime, and there is no way to ask a List<T> what T is. A direct consequence: you cannot new T[n] inside a generic class — the compiler can't erase that to anything meaningful.

java
import java.util.*;

List<String> ls = new ArrayList<>();
List<Integer> li = new ArrayList<>();

System.out.println("List<String> and List<Integer> share a runtime class: " + (ls.getClass() == li.getClass()));
System.out.println("runtime class: " + ls.getClass());
System.out.println("`ls instanceof List<String>` even compiles down to a raw `instanceof List` check --");
System.out.println("the type argument gives no runtime discrimination at all: " + (ls instanceof List<String>));

And here's the actual compiler error you get if you try to create a generic array directly (captured from a real javac run, not paraphrased):

java
// Reproduced verbatim from `javac` on:
//   class GenArr<T> { T[] makeArray(int n) { return new T[n]; } }
//
// GenArr.java:4: error: generic array creation
//         return new T[n];
//                ^
// 1 error
System.out.println("(see markdown/comment above -- this is a compile-time error, can't be caught at runtime)");

Interview angle

A deep-cut but common senior-level question — "why can't you do new T[]?" or "why is list instanceof List<String> meaningless?" — specifically used to separate candidates who've internalized how generics actually work at the bytecode level from those who've only used generics as type-safety syntax without thinking about what the compiler does with them.

In the industry

Understanding erasure is essential for reading and writing generic library code — collections, builders, and reflection-based frameworks like Jackson or Gson have to work around it explicitly (via patterns like TypeToken/TypeReference) to recover type information erasure throws away. Most application-level code never has to think about this directly, but anyone writing a reusable generic API or debugging a ClassCastException from an unchecked-warning code path hits it immediately.