Generics & Typescritical

Type Erasure

Java generics are erased at compile time — generic type parameters are replaced with their bounds (Object if unbounded). At runtime, List<String> and List<Integer> are both just List.

Memory anchor

Type erasure = wearing a name tag at a costume party, but the bouncer rips off all tags at the door. Inside the party (runtime), List<String> and List<Integer> are both just 'List' -- nobody remembers who's who.

Expected depth

Type erasure consequences: you cannot do new T[], instanceof List<String>, or get the generic type T at runtime via reflection from a normal class (only from class literals, supertype tokens, or TypeToken). The compiler inserts unchecked casts at usage sites. Bridge methods are generated for overrides of generic methods to maintain binary compatibility. Reifiable types (whose full type is available at runtime): raw types, non-generic types, arrays of reifiable types, wildcards (List<?>). Non-reifiable: List<String>, Map<K,V>.

Deep — senior internals

Heap pollution: a variable of type List<String> can hold a List<Integer> at runtime if an unchecked cast is involved (the JVM can't check it). This produces an unchecked warning at compile time. @SafeVarargs suppresses heap pollution warnings for methods whose varargs parameter is not modified. TypeToken (Guava) / ParameterizedType (java.lang.reflect) enable runtime capture of generic types by creating an anonymous subclass (List<String>{} captures the type argument). The Reflection API's Type hierarchy (ParameterizedType, TypeVariable, WildcardType, GenericArrayType) represents generic signatures in class files even though erasure removes them from the runtime.

🎤Interview-ready answer

Java generics are compile-time only — type parameters are erased to their bounds (usually Object) in bytecode. This means you can't instantiate a generic type parameter (new T()), check instanceof with a parameterized type (x instanceof List<String>), or create generic arrays (new T[]). Unchecked casts are inserted by the compiler at usage sites. The upside: generics are backward-compatible with pre-Java-5 raw type code. Use TypeToken or Class<T> tokens when you need runtime type information.

Common trap

Overloading methods that differ only by generic type parameter (void process(List<String>) and void process(List<Integer>)) causes a compile error — after erasure both have the same signature void process(List).