Lesson Completion
Back to course

Type Erasure: How Generics Work at Runtime

Advanced
15 minutes4.8Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Type erasure removes all generic type information at runtime for backward compatibility with pre-Java 5 code. List<String> and List<Integer> become just List (raw type) in bytecode.
  • Implications: Cannot create generic arrays, cannot use instanceof with generics, cannot instantiate type parameters. Generics = compile-time only feature!

Think of security checkpoint. Generics = ID check at entrance (compile-time). After entering, no one checks IDs again (runtime = type erased)!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy: The Temporary Label

Generic type = sticky note with "BOOKS ONLY". Compiler reads it, then throws away the note before shipping!


3. Technical Mastery (The "Deep Dive")

Erasure Process

java
// BEFORE ERASURE (source code) List<String> strings = new ArrayList<>(); strings.add("Hello"); String s = strings.get(0); // AFTER ERASURE (bytecode equivalent) List strings = new ArrayList(); strings.add("Hello"); String s = (String) strings.get(0); // Compiler inserts cast!

Bounded Types Erase to Bound

java
// BEFORE class Box<T extends Number> { private T value; public T get() { return value; } } // AFTER (erases to upper bound) class Box { private Number value; // T → Number public Number get() { return value; } }

4. Interactive & Applied Code

java
import java.util.*; public class TypeErasureDemo { public static void main(String[] args) { demonstrateErasure(); demonstrateRestrictions(); } static void demonstrateErasure() { // Same class at runtime! List<String> strings = new ArrayList<>(); List<Integer> ints = new ArrayList<>(); System.out.println("Same class? " + (strings.getClass() == ints.getClass())); // true! System.out.println("Class: " + strings.getClass().getName()); // java.util.ArrayList (no <String>!) // CANNOT use instanceof with generics // if (strings instanceof List<String>) {} // ❌ Compile error if (strings instanceof List) {} // ✅ OK (raw type) } static void demonstrateRestrictions() { // ❌ CANNOT create generic array // List<String>[] array = new List<String>[10]; // Compile error // ✅ WORKAROUND: Use ArrayList instead List<List<String>> listOfLists = new ArrayList<>(); // ❌ CANNOT instantiate type parameter // <T> T create() { return new T(); } // Compile error // ✅ WORKAROUND: Use Class<?> parameter <T> T create(Class<T> clazz) throws Exception { return clazz.getDeclaredConstructor().newInstance(); } } // Bridge method example static class Node<T> { private T data; public void setData(T data) { this.data = data; } public T getData() { return data; } } static class IntegerNode extends Node<Integer> { // Overrides setData(Integer) @Override public void setData(Integer data) { super.setData(data); } // Compiler generates BRIDGE method: // public void setData(Object data) { // setData((Integer) data); // } // This maintains polymorphism with erased parent method! } }

5. The Comparison & Decision Layer

What Exists Where?

FeatureCompile-TimeRuntime
Generic type info✅ Full info❌ Erased
Type checking✅ Strict❌ None
Type parameters<T>❌ Becomes Object/bound
Casts❌ Not needed✅ Auto-inserted

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "Why can't you create a generic array in Java?" Answer: Because of type erasure + array covariance = heap pollution!

java
// ❌ ILLEGAL: Would break type safety! // List<String>[] array = new List<String>[10]; // If allowed, this could happen: // Object[] objArray = array; // Arrays are covariant // objArray[0] = new ArrayList<Integer>(); // Compiles! // String s = array[0].get(0); // ClassCastException!

Solution: Use ArrayList<List<String>> or @SafeVarargs for varargs.

Pro-Tip: Retain type info with anonymous class (super type token pattern):

java
// Type info is ERASED List<String> list = new ArrayList<>(); // Type info is PRESERVED (via anonymous class!) List<String> list = new ArrayList<String>() {}; // The {} creates anonymous subclass which retains parent's <String> // Used by Gson, Jackson for deserialization: Type type = new TypeToken<List<String>>() {}.getType();

This tricks Java into preserving generic type info!

Topics Covered

Java FundamentalsAdvanced Java

Tags

#java#generics#type-safety#reusability

Last Updated

2025-02-01