Type Erasure
TL;DR
- Type Erasure is the process where the Java compiler removes all Generic type information during compilation.
- At runtime, the JVM has no idea what a generic type parameter was; it simply sees raw classes and
Objects. - This was done to ensure backward compatibility with older versions of Java (pre-Java 5).
Concept
When you write List<String>, it exists only in your source code. The Java compiler enforces type safety, ensuring you only add Strings. Once it is satisfied, it compiles the code to bytecode.
During this compilation, it erases <String>. In the compiled .class file, it just becomes a raw List. If the generic type is unbounded (<T>), the compiler replaces it with Object. If it is bounded (<T extends Number>), the compiler replaces it with the bound (Number). It also automatically inserts type casting where necessary.
Why was this done?
When Generics were introduced in Java 5, millions of lines of legacy Java code already existed using raw Lists. The creators of Java chose Type Erasure so that new Generic code could compile into the exact same bytecode as legacy code, allowing them to interact seamlessly.
Examples
// --- What you write in your source code ---
public class Node<T> {
private T data;
public void setData(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
public class Main {
public static void main(String[] args) {
Node<String> node = new Node<>();
node.setData("Hello");
String text = node.getData();
}
}
// --- What the Compiler generates (Type Erasure) ---
/*
public class Node {
private Object data; // T erased to Object
public void setData(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
}
public class Main {
public static void main(String[] args) {
Node node = new Node();
node.setData("Hello");
// Compiler automatically inserts the cast!
String text = (String) node.getData();
}
}
*/
Interview Questions
Q: Can you use Generics in an instanceof check (e.g., if (obj instanceof List<String>))?
A: No, you cannot. Because of Type Erasure, <String> does not exist at runtime. The JVM only sees a raw List object. Therefore, you can only check if (obj instanceof List). Checking against a parameterized type causes a compile-time error.
Q: Can you write two methods that differ only by their Generic type parameters (Method Overloading)?
A: No. For example, public void print(List<String> list) and public void print(List<Integer> list) will result in a compile error. Because of Type Erasure, both methods compile down to public void print(List list). The compiler forbids this because it results in a method signature clash in the bytecode.