Skip to content

How to Handle Java Generic Type Erasure

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about How to Handle Java Generic Type Erasure. We cover key concepts, practical examples, and best practices.

The Problem

Your Java code fails with java.lang.ClassCastException at runtime, unchecked cast warnings, or illegal generic type for instanceof. Generics in Java are erased at runtime — List<String> becomes List, making type information unavailable.

Quick Fix

Fix 1: instanceof with Generics

WRONG — checking generic type at runtime:

if (obj instanceof List<String>) { }  // Compile error: illegal generic type for instanceof

RIGHT — use wildcard or raw type:

if (obj instanceof List) {
    List<?> list = (List<?>) obj;
    for (Object item : list) {
        if (item instanceof String) {
            System.out.println("String element: " + item);
        }
    }
}

Fix 2: Generic Array Creation

WRONG — creating an array of generic type:

List<String>[] array = new List<String>[10];  // Compile error: generic array creation

RIGHT — use ArrayList of lists or raw type with cast:

@SuppressWarnings("unchecked")
List<String>[] array = new List[10];  // raw type, safe if used consistently
// Or better:
List<List<String>> listOfLists = new ArrayList<>();

Fix 3: Passing Class as Parameter (Type Token)

WRONG — losing generic type information:

class JsonParser {
    public <T> T parse(String json) {
        // Cannot create T: return new T();  // not possible
        return null;  // caller gets a raw Object that needs casting
    }
}

RIGHT — pass the Class token:

class JsonParser {
    public <T> T parse(String json, Class<T> clazz) {
        // Use clazz for type-safe deserialization:
        // return objectMapper.readValue(json, clazz);
        return clazz.cast(json);  // example
    }
}

// Usage:
MyClass obj = parser.parse(json, MyClass.class);

Fix 4: Super Type Token (for Complex Generics)

When you need List<String> as a type at runtime:

import com.google.common.reflect.TypeToken;

// Using Guava's TypeToken:
TypeToken<List<String>> typeToken = new TypeToken<List<String>>() {};
java.lang.reflect.Type type = typeToken.getType();

Or manually:

abstract class TypeReference<T> {
    private final Type type;

    protected TypeReference() {
        Type superClass = getClass().getGenericSuperclass();
        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    public Type getType() { return type; }
}

// Usage:
TypeReference<List<String>> ref = new TypeReference<List<String>>() {};
System.out.println(ref.getType());  // java.util.List<java.lang.String>

Fix 5: Unchecked Cast Warning

@SuppressWarnings("unchecked")
List<String> strings = (List<String>) someList;  // unchecked cast warning

RIGHT — minimize the scope of suppression:

@SuppressWarnings("unchecked")
private List<String> castToStringList(Object obj) {
    return (List<String>) obj;
}

Fix 6: Bridge Methods (Synthetic Methods)

class Parent {
    public Object getValue() { return null; }
}

class Child extends Parent {
    @Override
    public String getValue() { return "value"; }  // bridge method added by compiler
}
// The compiler generates a synthetic bridge method: Object getValue() { return this.getValue(); }

Use DodaTech's Type Safety Analyzer to detect raw type usage, unchecked casts, and erasure-related bugs in your Java codebase.

Prevention

  • Avoid instanceof with parameterized types.
  • Use Class<T> parameters when runtime type is needed.
  • Prefer wildcards (?) over raw types.
  • Use Guava's TypeToken for complex generic types.
  • Suppress unchecked warnings only with explicit justification.

Common Mistakes with generic type erasure

  1. Misunderstanding that String is [Char] with poor performance for large text operations
  2. Using foldl instead of foldl' causing stack overflow on large lists
  3. Forgetting deriving (Show, Eq) on custom data types needed for debugging

These mistakes appear frequently in real-world JAVA code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What is type erasure in Java?

Type erasure means generic type information is removed at compile time and is not available at runtime. List<String> and List<Integer> both become just List. The compiler ensures type safety, but the runtime sees only raw types.

Why can't I create an array of generic type?

Arrays are reified (type information is retained at runtime), but generics are erased. Creating new List<String>[10] would allow storing a List<Integer> in what appears to be a List<String> array. Java prohibits this to maintain type safety.

How does the bridge method help with generics?

Bridge methods are synthetic methods created by the compiler to maintain polymorphism when generic types change in subclasses. They have erased signatures that match the parent class and delegate to the actual method. This ensures correct overriding behavior.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro