java泛型在编译后被擦除,但类型信息通过signature等属性保留在class文件中;反射需用getgenericxxx()系列方法(如getgenericsuperclass、getgenericinterfaces、getgenerictype)获取parameterizedtype等并提取实际类型参数。

Java 泛型在编译后会被擦除,但编译器会将泛型的类型信息以 Signature 属性形式保留在 class 文件中(如 Signature、RuntimeVisibleTypeAnnotations 等)。反射中可通过 java.lang.reflect 相关 API 读取这些元数据,从而还原泛型的实际类型参数——关键在于使用 getGenericXxx() 系列方法,而非普通 getXxx() 方法。
用 getGenericSuperclass() 获取父类泛型实参
适用于继承了带泛型的父类(如 class A extends B<string></string>),此时可通过子类 Class 对象获取其泛型父类的完整类型信息:
-
Class.getGenericSuperclass()返回Type,若为ParameterizedType,则可调用getActualTypeArguments()提取实际类型参数 - 注意:返回的是
Type数组,可能是Class、ParameterizedType或TypeVariable,需按需向下转型 - 示例:
((ParameterizedType) A.class.getGenericSuperclass()).getActualTypeArguments()[0]可得String.class
用 getGenericInterfaces() 获取接口泛型实参
当类实现泛型接口(如 class C implements List<integer></integer>)时,同理使用:
-
Class.getGenericInterfaces()返回Type[],遍历并识别出ParameterizedType - 对匹配的接口类型调用
getActualTypeArguments(),即可获得Integer这类具体类型 - 若接口本身是类型变量(如
T extends List<e></e>),则可能得到TypeVariable,需结合上下文进一步解析
字段/方法/构造器的泛型类型通过 getGenericType() 获取
成员声明处的泛型(如 private List<string> list;</string> 或 <t> T get()</t>)需分别调用:
-
Field.getGenericType()→ 若为ParameterizedType,可提取List的实际参数String -
Method.getGenericReturnType()和Method.getGenericParameterTypes()同理,用于返回值和参数中的泛型 - 注意:仅当源码中明确写了泛型(如
List<string></string>)才会保留签名;裸类型(List)或原始类型(raw type)不产生Signature信息
处理嵌套与通配符类型
Signature 支持较复杂的泛型结构,反射 API 也提供了对应支持:
-
WildcardType表示通配符(如? extends Number),可通过getUpperBounds()/getLowerBounds()获取边界 -
ParameterizedType的getOwnerType()用于内部类场景(如Outer<k>.Inner<v></v></k>) -
TypeVariable表示声明时的类型变量(如<t></t>),其getBounds()返回上界约束,但运行时无法知道具体实参——除非该变量出现在某个已参数化的上下文中(如方法调用栈中已知实参)
不复杂但容易忽略:所有 getGenericXxx() 方法返回的都是“泛型视图”,它们依赖 class 文件中的 Signature 属性,因此必须基于真实编译后的字节码(即不能只靠源码推断),且只有显式声明的泛型才会被记录。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











