Java泛型在运行时通过反射可获取类型信息,关键是在编译前以ParameterizedType或TypeReference方式保留泛型实参,仅对直接声明的父类/接口泛型有效,局部变量泛型无法恢复。

Java 泛型在编译期被擦除,运行时无法直接获取泛型类型参数(如 List 中的 String),但通过反射配合特定的编码约定(如继承 TypeReference、使用 ParameterizedType),可以在运行时“找回”泛型信息。关键不在于“绕过类型擦除”,而是在擦除发生前,把类型信息以可反射的方式保留下来。
利用 ParameterizedType 获取父类/接口的泛型实参
这是最常用且可靠的方式:当一个类显式继承或实现带泛型的父类/接口时(如 class MyList extends ArrayList),JVM 会在该类的 Class 对象中保留其父类的完整参数化类型,可通过反射提取。
- 调用
getClass().getGenericSuperclass()或getGenericInterfaces(),返回的是Type,需强转为ParameterizedType - 检查是否为
ParameterizedType,再调用getActualTypeArguments()获取实际类型参数数组 - 注意:仅对**直接声明**的泛型有效(如继承
ArrayList可取到User;但局部变量List无法反射获取)list
示例:
public class UserRepo extends BaseDao<user> {
public Class<user> getEntityClass() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
Type[] args = ((ParameterizedType) superclass).getActualTypeArguments();
if (args.length > 0 && args[0] instanceof Class) {
return (Class<user>) args[0];
}
}
throw new RuntimeException("Cannot resolve entity type");
}
}</user></user></user>
用 TypeReference 模拟匿名子类保存泛型信息
适用于需要在方法调用处“捕获”泛型类型(如 JSON 反序列化、泛型 DAO 查询)。原理是创建一个匿名子类(如 new TypeReference),利用其 >(){}
getGenericSuperclass() 保留类型信息。
- 定义抽象基类
TypeReference,构造器中调用getClass().getGenericSuperclass() - 子类实例(匿名类)的父类就是
TypeReference,其中- >
List是完整的ParameterizedType - 避免直接用
new TypeReference,应封装成 final 字段或方法返回,防止被 JIT 优化掉- >(){}.getType()
常见于 Jackson、Fastjson 的 TypeReference 实现,也适用于自定义泛型工具类。
处理嵌套泛型与类型变量(TypeVariable)
当泛型参数本身是类型变量(如 class Box)时,反射拿到的是 TypeVariable,不是具体类型。需结合上下文推导:
- 若
Box是某个字段的类型,可通过Field.getGenericType()→ParameterizedType→getActualTypeArguments()得到String - 若只有
Box(无实参),则T是TypeVariable,需查其getBounds()(如返回Number) - 复杂嵌套(如
Map)需递归解析每个> Type元素,区分ParameterizedType、WildcardType、GenericArrayType
注意事项与局限
泛型 + 反射不是万能的,必须清楚边界:
- 局部变量和方法参数的泛型永远丢失:编译后只剩原始类型,反射无法恢复
-
泛型数组类型需用
GenericArrayType判断(如T[]),不能简单当作Class -
桥接方法(bridge methods)可能干扰反射结果:编译器生成的桥接方法会暴露原始类型签名,需用
Method.isBridge() == false过滤 -
Android 环境下部分反射行为受限,尤其是高版本对私有 API 的限制,
sun.misc.Unsafe等不可用
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











