java反射获取泛型真实类型本质是查字节码中已保留的泛型签名,而非运行时计算;仅字段、方法签名、父类继承中写死的泛型可被读取,局部变量等动态泛型不可见。

Java 反射获取泛型真实类型,核心不是“算”,而是“查”——从字节码里已保留的泛型签名中提取信息,不是运行时推导或计算出来的。
关键前提:泛型必须写死在类结构里
只有字段声明、方法签名、父类继承关系中明确写出的泛型(如 private List<user> users;</user> 或 class Service extends BaseService<order></order>),才能被反射读到。局部变量、new ArrayList<string>()</string> 这类动态构造的泛型,字节码里没存,反射也找不到。
最常用入口:getGenericType() 和 getGenericSuperclass()
- 字段泛型:用
Field.getGenericType()→ 判断是否为ParameterizedType→ 调getActualTypeArguments()拿出真实类型数组 - 父类泛型:用
Class.getGenericSuperclass()→ 同样判ParameterizedType→ 取getActualTypeArguments()[0]得到实参类型(如User.class) - 方法泛型:用
Method.getGenericReturnType()或getGenericParameterTypes(),逻辑一致
类型要逐层拆解,不能硬转 Class
泛型参数不一定是 Class,可能是:
-
Class>:直接强转可用,比如String.class -
ParameterizedType:比如List<map integer>></map>中的Map<string integer></string>,需再次调getActualTypeArguments()递归解析 -
TypeVariable:如方法声明<t> T get()</t>,反射只拿到变量名和上界(getBounds()[0]),没有具体类型 -
WildcardType:如? extends Number,需用getUpperBounds()查上限
别踩这些坑
-
list.getClass().getGenericSuperclass()拿不到ArrayList<string></string>的String—— 因为ArrayList自身定义是ArrayList<e></e>,E是类型变量,没绑定值 -
getParameterTypes()和getReturnType()返回的是擦除后的原始类型,必须用带Generic前缀的方法 - 私有方法、桥接方法、未重写的继承方法,泛型信息可能缺失或不完整
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











