Fundamentals 7 min read

How to Retrieve Generic Types at Runtime with Gson’s TypeToken

This article explains Java's generic type erasure, why it exists, and demonstrates how to use Gson's TypeToken and reflection APIs to obtain actual generic type information at runtime, complete with code examples and a detailed walkthrough of the underlying mechanism.

Programmer DD
Programmer DD
Programmer DD
How to Retrieve Generic Types at Runtime with Gson’s TypeToken

Overview

By analyzing the principle of TypeToken, we deepen our understanding of generic type erasure, enabling us to know when and how we can obtain the actual generic type.

Generic Erasure

Java generics are only effective at compile time; at runtime the generic type is erased, so List<String> and List<Integer> both become List<Object>.

This design ensures backward compatibility of existing class files and allows generic and non‑generic code to interoperate, which is why Java adopted type erasure instead of preserving generic information.

TypeToken

Usage

When using Gson, you define a TypeToken to specify the target type for deserialization, for example:

private Type type = new TypeToken<List<Map<String, Foo>>>(){}.getType();
// Pass the type to fromJson; if it matches the JSON structure, Gson can deserialize correctly.
gson.fromJson(json, type);

Three Questions

Why use TypeToken? Directly passing List&lt;Map&lt;String, Foo&gt;&gt; would be erased to List&lt;Object&gt; , causing Gson to default to LinkedTreeMap instead of the desired Map&lt;String, Foo&gt; .

Why the curly braces {} ? They create an anonymous subclass of TypeToken, which is essential for capturing the generic type.

Why obtain the generic type via a subclass? The subclass retains the generic parameter information in its class metadata, which can be accessed through reflection APIs such as Class.getGenericSuperclass() and ParameterizedType.getActualTypeArguments() .

Type mySuperClass = foo.getClass().getGenericSuperclass();
Type type = ((ParameterizedType)mySuperClass).getActualTypeArguments()[0];
System.out.println(type);

The method Class.getGenericSuperclass() returns a ParameterizedType for classes with generic superclasses, or null for Object, interfaces, primitives, or arrays.

Principle

The core of TypeToken lies in its constructor, which calls getSuperclassTypeParameter(getClass()) to capture the actual type argument of the anonymous subclass.

public final Type getType() {
    // directly returns the captured type
    return type;
}
protected TypeToken() {
    this.type = getSuperclassTypeParameter(getClass());
    this.rawType = (Class<?>) $Gson$Types.getRawType(type);
    this.hashCode = type.hashCode();
}

static Type getSuperclassTypeParameter(Class<?> subclass) {
    Type superclass = subclass.getGenericSuperclass();
    if (superclass instanceof Class) {
        throw new RuntimeException("Missing type parameter.");
    }
    ParameterizedType parameterized = (ParameterizedType) superclass;
    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}

Summary

After understanding the underlying mechanism, you can reliably retrieve generic type information at runtime using Gson's TypeToken and Java reflection.

References

https://www.cnblogs.com/doudouxiaoye/p/5688629.html

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaReflectionRuntimeGenericsGsonTypeToken
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.