Type Erasure in Java

Last Updated : 22 Nov, 2025

Type Erasure is the process by which the Java compiler removes all generic type information and replaces type parameters with their upper bounds (or Object if unbounded).

During compilation, the compiler performs:

  • Replacing type parameters with their upper bound or Object.
  • Inserting casts where needed to maintain type safety.
  • Generating bridge methods to preserve method overriding in generic hierarchies.

Note: After compilation, no generic type exists in the bytecode. Only raw types remain.

How Type Erasure Works

Now, we are going to discuss how Type Erasure works in Java

1. Unbounded Type Example

JAVA
// Here, T is unbounded (default bound: Object)
class GFG<T>{
    
    T obj;

    GFG(T o) {
        obj = o;
    }

    T getob() {
        return obj;
    }
}


After Type Erasure

Java
class GFG{
    
    Object obj;

    GFG(Object o){
        
        obj = o;
    }

    Object getob(){
        
        return obj;
    }
}

Since T has no explicit bound, it is replaced with Object.

2. Bounded Type Example

JAVA
class Geeks<T extends String>{
    
    T str;

    Geeks(T o) {
        str = o;
    }

    T getob() {
        return str;
    }
}

After Type Erasure

Java
class Geeks{
    
    String str;

    Geeks(String o){
        
        str = o;
    }

    String getob(){
        
        return str;
    }
}

Here, T is bounded by String, so it is replaced with String.

Viewing Erased Bytecode

After compiling the classes, you can inspect their contents using:

javap GFG
javap Geeks

These will show that the type parameters no longer exist at runtime.

Type Erasure in Action

Now, we will see example to understand ow type erasure affects code during runtime.

Example 1: Using Generics

Java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Geeks{
    
    public static void main(String args[]){
        
        List<String> list = new ArrayList<>();
        list.add("Hello");

        Iterator<String> iter = list.iterator();
        while (iter.hasNext()) {
            String s = iter.next();
            System.out.println(s);
        }
    }
}

Output
Hello

Explanation:

  • Compiler checks type safety -> OK (String list)
  • At runtime, the generic type (String) does not exist.
  • Type casts inserted by compiler ensure safety.

Example 2: Raw Types

JAVA
import java.util.*;

public class Geeks{

    public static void main(String args[]){
        
        List list = new ArrayList();   // Raw type
        list.add("Hello");

        String s;
        for (Iterator iter = list.iterator(); iter.hasNext(); ) {
            s = (String) iter.next();
            System.out.println(s);
        }
    }
}

Output:

./Geeks.java uses unchecked or unsafe operations.
Recompile with -Xlint:unchecked for details.

Explanation: In the above example, we are using raw types, it simply means we are not specifying the type if datat the the list will hold. In this case, the compiler will throw a warning GenericsErasure.java uses unchecked or unsafe operations. The reason for the warning is that raw types don not carry any type information.

Issues Caused by Type Erasure

The issues caused by Type Erasure is listed below:

  • The JVM loses information of the generic type at runtime, that's why we can not use instanceof or create new instances of generic types.
  • When we work with raw types, the compiler will give warning.
  • We can not create array of generic types directly.
Comment