Java泛型存在类型擦除,TypeToken通过匿名子类在编译期捕获泛型信息并保留至运行时,从而安全获取实际类型参数,如List<String>中的String。

Java 运行时无法直接获取 List<String> 这样的泛型类型,因为泛型在编译后会被擦除(type erasure)。但借助 Google Guava 的 TypeToken,可以**在编译期“捕获”泛型信息并保留到运行时**,从而安全地获取泛型参数。
为什么需要 TypeToken?
普通写法如 new ArrayList<String>().getClass() 只能得到 ArrayList.class,丢失了 <String> 信息。而 TypeToken<List<String>>() {} 利用匿名子类的 getGenericSuperclass(),让 JVM 在字节码中保留泛型结构,进而解析出实际类型参数。
基本用法:获取 List 的泛型元素类型
以获取 List<User> 中的 User 类型为例:
// 正确:用匿名子类“固化”泛型信息TypeToken<List<User>> token = new TypeToken<List<User>>() {};Type elementType = token.getType(); // 整个 List<User> 类型Type listType = token.getRawType(); // Class<List>Type[] typeArgs = ((ParameterizedType) elementType).getActualTypeArguments(); // [User]Class<?> elementClass = (Class<?>) typeArgs[0]; // User.class
通过 Auth0 Token Vault,代表已认证用户访问 Gmail、Slack、Google Calendar、GitHub 等第三方服务以及自定义 Auth0 连接。使用...
实用封装:提取泛型元素 Class
可封装成通用方法,避免每次手动强转:
立即学习“Java免费学习笔记(深入)”;
public static <T> Class<T> getElementType(TypeToken<? extends Collection<T>> token) { Type type = token.getType(); if (type instanceof ParameterizedType) { Type[] args = ((ParameterizedType) type).getActualTypeArguments(); if (args.length == 1 && args[0] instanceof Class) { return (Class<T>) args[0]; } } throw new IllegalArgumentException("无法解析泛型元素类型");}
调用:Class<User> clazz = getElementType(new TypeToken<List<User>>() {});
注意事项与常见坑
-
必须用匿名子类语法:
new TypeToken<List<String>>() {}—— 少了{}就只是普通泛型实例,无法保留类型信息 -
不能用于局部变量泛型推断:比如
TypeToken<List<T>> t = ...中的T是未绑定的类型变量,运行时仍为Object -
嵌套泛型需逐层解析:如
List<Map<String, Integer>>,需先取List的第一个参数(即Map<String, Integer>),再对它做二次解析 -
依赖 Guava:确保引入
com.google.guava:guava(≥20.0)

















