Java.Core.Generics.TypeErasure

🔹 What is Type Erasure?

Type erasure is a process performed by the Java compiler when working with generics.

In short:

The compiler removes (erases) all generic type information during compilation, replacing it with raw types or bounds (like Object or upper bounds if specified).


🔹 Why Does It Exist?

Backward Compatibility

Generics were introduced in Java 5. To maintain compatibility with older versions of Java (pre-Generics), the compiled bytecode could not contain actual type parameters.

This way, code with generics can still run on JVMs that existed before generics were introduced.


🔹 What Happens During Erasure?

Example

List<String> list = new ArrayList<>();
list.add("Hello");
String item = list.get(0);

After type erasure, this is roughly how the compiled code looks like:

List list = new ArrayList();
list.add("Hello");
String item = (String) list.get(0);  // Cast inserted by the compiler

🔹 How Does Erasure Work?

There are 3 main rules for type erasure:

1️⃣ Remove Type Parameters

Type parameters like <T> or <E> are removed from the compiled code.

Example:

class Box<T> { T value; }

Becomes:

class Box { Object value; }

2️⃣ Replace with Upper Bound (if any)

If the generic type has a bound, it gets replaced by that bound.

Example:

class Box<T extends Number> { T value; }

Becomes:

class Box { Number value; }

3️⃣ Insert Casts Where Necessary

To preserve type safety, the compiler inserts casts where needed.

T value = list.get(0);

Becomes:

Object obj = list.get(0);
T value = (T) obj;

🔹 Key Consequences of Type Erasure

⚠️ No Runtime Generics Information

After erasure, generic type information (like T or String) is gone at runtime. This is why:

List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
System.out.println(list1.getClass() == list2.getClass());  // true

Cannot Use instanceof with Generics

This won’t compile:

if (list instanceof List<String>) {  // Compile error!
}

Because after erasure, List<String> just becomes List.


⚠️ Arrays with Generics are Unsafe

This is why you cannot create generic arrays directly:

List<String>[] array = new ArrayList<String>[10];  // Compile error

⚠️ Reflection Loses Type Parameters

When you inspect a generic class using reflection, you cannot see the actual type arguments used at runtime.

✅ Workarounds (Type Tokens)

If you need to retain generic type information (like in frameworks/libraries), you can pass a Class<T> or a TypeReference<T> to methods so they know the type at runtime.

Example:

public <T> T parse(String json, Class<T> clazz) { ... }

🔹 Quick Summary

What?After Type Erasure
List<String>List
Box<T>Box
TObject (or upper bound)
Type checkingHappens at compile-time only
This entry was posted in Без рубрики. Bookmark the permalink.