Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java type erasure: validate elements with an explicit Class token

Last updated: 5 Oct 20265 min read
tutorial
AdvancedBy AITrove Editorial

Java erases most generic type arguments from runtime class identity. A Class token can validate each element when an unchecked external list crosses into a typed API.

Operational contract

The method accepts a List<?> from an untyped integration boundary and a requested element class. Class.cast checks each value and creates a fresh List<T>. It rejects null input and null elements before List.copyOf, which itself does not allow null members. The token checks the runtime class of each element; it cannot validate a nested type such as List<String> inside a List<List<String>>. A wire-format parser must still validate field meaning, range, and schema. Two overloads that differ only by List<String> versus List<Long> are illegal because their erased signatures collide.

Failure case

A plug-in returns 23 raw receipt values, and the application expects String IDs. The first Long value fails at the boundary with ClassCastException rather than much later inside a billing routine. Calling getClass on the list itself would reveal its implementation class, not its erased element argument.

Java code

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

public class TypedReceiptBoundary {
    public static <T> List<T> checkedCopy(List<?> incoming, Class<T> elementType) {
        Objects.requireNonNull(incoming);
        Objects.requireNonNull(elementType);
        if (incoming.size() > 47) throw new IllegalArgumentException("Too many values");
        List<T> checked = new ArrayList<>(incoming.size());
        for (Object value : incoming) checked.add(elementType.cast(value));
        return List.copyOf(checked);
    }
}

Performance and ownership cost

Validation and copying take O(N) time and O(N) new list storage for N values, capped at 47. Class.cast checks each runtime element; the one-time copy also prevents later mutations of the incoming list from changing the returned membership.

Common Mistakes

  • Do not expect a List instance to retain its String or Long type argument at runtime.
  • Do not use Class<T> to claim validation of nested generic arguments.
  • Do not defer unchecked casts until after data enters domain logic.

Connected lessons

java
generics at api boundaries
generic-erasure-runtime-type-check
Storage details