java泛型虽在运行时被擦除,但通过反射可获取保留于类签名中的泛型信息:从父类继承关系(如getgenericsuperclass())、方法参数/返回值(getgenericparametertypes())中提取parameterizedtype,并递归解析嵌套、通配符及类型变量;局部变量、原始类型调用等场景则无法恢复。

Java泛型在编译期被擦除,运行时无法直接获取 T 的真实类型 —— 但这不是绝对的。只要泛型信息以“结构化方式”保留在类签名中(如继承父类、实现接口、方法参数/返回值声明),就能通过反射配合 ParameterizedType 拿到具体类型。
从父类继承关系中提取泛型类型
这是最稳定、最常用的方式。当子类显式指定父类泛型时,JVM 会把该类型写入字节码的 Signature 属性,反射可读取。
- 调用
getClass().getGenericSuperclass()获取带泛型的父类类型 - 判断是否为
ParameterizedType,是则强转 - 用
getActualTypeArguments()[0]取出第一个泛型实参(如User.class) - 若实参是
Class类型,可安全转为Class<t></t>;若是ParameterizedType(如List<string></string>),需递归解析
从方法参数或返回值中获取泛型
方法签名中的泛型不会被擦除,比如 void process(List<order> list)</order>,可通过 Method 对象提取。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 用
clazz.getMethod("process", List.class)获取目标方法 - 调用
method.getGenericParameterTypes()或getGenericReturnType() - 对每个
Type判断是否为ParameterizedType -
getRawType()返回原始类型(如List.class),getActualTypeArguments()返回泛型参数数组(如[Order.class])
注意类型边界与嵌套场景
泛型实参不一定是 Class,还可能是 WildcardType(如 ?、? extends Number)、TypeVariable(如方法泛型 <t> T get()</t>)或更深层的 ParameterizedType(如 Map<string list>></string>)。
- 遇到
WildcardType,可用getUpperBounds()或getLowerBounds()获取上下界 -
TypeVariable在运行时无具体类型,必须靠外部传入TypeToken或约定规则推断 - 嵌套泛型需逐层展开:先取
Map<k></k>的V,再判断它是否仍是ParameterizedType,继续取其getActualTypeArguments()
不能获取泛型的典型情况
泛型擦除的本质决定了某些场景下确实不可恢复:
- 仅声明泛型变量但未在继承/实现/方法签名中固化,例如
List<string> list = new ArrayList();</string>—— 运行时只剩List.class - 泛型出现在局部变量、方法形参(未标注类型)、或泛型方法体内部
- 使用原始类型(raw type)调用,如
new ArrayList(),连getGenericSuperclass()都返回ArrayList.class而非ParameterizedType
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










