Get generic type of class at runtime
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Getting a generic type at runtime depends heavily on the language and on how the generic system is implemented. In Java, this question usually runs into type erasure, which means many generic type details do not exist at runtime unless you preserve them explicitly.
Why the Type Is Often Unavailable
Java generics improve compile-time safety, but most parameterized type information is erased from ordinary objects at runtime. For example, List<String> and List<Integer> both become just List at runtime.
Output:
That is the core reason this problem exists.
Strategy 1: Pass a Class<T> Token
The most reliable solution is to keep the type yourself by passing a Class<T> value into the object or method.
This works because you are not asking Java to recover erased information. You are preserving the type token explicitly.
Strategy 2: Inspect a Parameterized Superclass
If a class directly extends a generic base type with concrete arguments, that information can often be read through reflection.
This works only when the generic information is still present in the class hierarchy. It does not recover erased types from arbitrary object instances.
Strategy 3: Use a Type Reference Pattern
Frameworks such as Jackson and Guava use a “type token” or “type reference” pattern to preserve full parameterized types such as List<String>.
This is how libraries preserve nested generic information that a simple Class<T> token cannot represent.
What Will Not Work
Trying to ask a plain instance for its original type argument usually fails.
This tells you the runtime class, not the generic argument. If you did not preserve the type somewhere else, Java cannot reconstruct it for you.
Choosing the Right Approach
Use Class<T> when a raw class token is enough, such as String.class or User.class. Use a type-reference approach when you need full generic information such as Map<String, Integer>. Use reflective superclass inspection only when your class hierarchy actually captures the generic argument.
Common Pitfalls
The most common mistake is expecting obj.getClass() to reveal generic type arguments. It cannot recover erased type parameters.
Another mistake is assuming a Class<T> token can represent nested parameterized types. It can represent String.class, but not List<String>.class, because that syntax does not exist.
Developers also sometimes use reflection against a superclass without checking whether the superclass is actually parameterized in that context, which can lead to ClassCastException.
Summary
- In Java, generic type information is often erased at runtime.
- The safest solution is to preserve type information explicitly with a
Class<T>token or type reference. - Reflective superclass inspection works only when the class hierarchy retains the generic argument.
- '
obj.getClass()reveals the runtime class, not erased generic parameters.' - Choose the preservation strategy based on whether you need a raw class or a full parameterized type.

