通过反射,提取 Cat 类 泛型 父类 接口 属性 的具体类型参数
1.父类
- 用
Cat.class
拿到Class
对象,作为反射起点; - 调用
getGenericSuperclass()
拿到带泛型信息的父类类型; - 判断并转换为
ParameterizedType
,再用getActualTypeArguments()
提取泛型参数,最终可通过getTypeName()
等方法查看参数具体类型
1. Class<Cat> catClass = Cat.class;
- 作用:获取
Cat
类的Class
对象,这是反射的基础入口。通过Class
对象,能动态获取类的结构(比如父类、接口、方法等),后续对泛型父类的操作都基于它展开。
2. Type genericSuperclass = catClass.getGenericSuperclass();
- 作用:获取
Cat
类带有泛型信息的直接父类类型 。- 如果父类是泛型类(比如
class Cat extends Animal<String>
),它能保留泛型参数(如String
); - 若父类没使用泛型,返回结果和
getSuperclass()
类似(但类型是Class
)。
- 如果父类是泛型类(比如
- 对比:
getSuperclass()
只能获取父类的Class
对象,丢失泛型参数 。比如父类是ArrayList<String>
,用它拿到的是ArrayList.class
,看不到<String>
;]getGenericSuperclass()
能拿到包含<String>
的完整泛型父类信息 。
3. ParameterizedType
相关逻辑
- 判断与转换:
j
if(genericSuperclass instanceof ParameterizedType){ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; }
- 先通过
instanceof
判断父类类型是否是参数化类型(即带泛型的类型,如ArrayList<String>
、自定义泛型父类Animal<String>
) 。\ - 强转
- 转换后,就能通过
ParameterizedType
的 API 提取泛型参数。
- 先通过
getActualTypeArguments()
:Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
作用是获取泛型父类的实际类型参数 。- 比如父类是
Animal<String>
,调用后返回Type
数组,里面存着String.class
对应的Type
信息; - 若父类是
Map<String, Integer>
,则返回[String, Integer]
对应的Type
数组。
- 比如父类是
2.接口
// 1. 获取 Mouse 类的 Class 对象,反射的入口
Class<Mouse> mouseClass = Mouse.class; // 2. 获取 Mouse 类实现的所有接口的“泛型类型信息”
Type[] genericInterfaces = mouseClass.getGenericInterfaces(); // 3. 遍历每个接口的类型信息
for (Type g : genericInterfaces) { // 4. 判断接口是否是“参数化类型”(即带泛型的接口,比如 MyInterface<String>)if(g instanceof ParameterizedType){ // 5. 强转为 ParameterizedType,才能提取泛型参数ParameterizedType parameterizedType = (ParameterizedType) g; // 6. 获取接口的实际泛型参数(比如 <String> 里的 String)Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 7. 遍历泛型参数,输出类型名称for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); }}
}
getGenericInterfaces()
:
作用是获取当前类实现的所有接口的 “泛型类型信息” 。- 和普通
getInterfaces()
区别:getInterfaces()
只能拿到接口的Class
对象(丢失泛型参数); getGenericInterfaces()
能保留泛型信息(比如MyInterface<String>
完整保留)。
- 和普通
3.属性
public static void main(String[] args) throws Exception {// 1. 获取目标类的 Class 对象,作为反射入口Class<User> userClass = User.class; // 2. 获取指定字段的 Field 对象(getDeclaredField 支持任意访问修饰符字段)Field mapField = userClass.getDeclaredField("map"); // (可选)若字段为非 public,解除访问限制mapField.setAccessible(true); // 3. 获取字段带泛型信息的 Type 对象Type genericType = mapField.getGenericType(); // 4. 判断是否为参数化类型(带泛型的类型)if (genericType instanceof ParameterizedType) { // 强转为 ParameterizedType,用于解析泛型参数ParameterizedType parameterizedType = (ParameterizedType) genericType; // 5. 提取泛型的实际类型参数,返回 Type 数组Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 6. 遍历泛型参数,获取并输出类型名称for (Type typeArg : actualTypeArguments) { System.out.println(typeArg.getTypeName()); }}
}
- 获取 Class 对象:拿到目标类的反射入口,用于后续操作。
- 获取 Field 对象:通过
getField
/getDeclaredField
定位具体成员变量。 - 获取泛型类型:用
Field
的getGenericType
拿到带泛型信息的Type
对象。 - 判断并强转:检查
Type
是否为ParameterizedType
,是则强转,为解析泛型做准备。 - 提取泛型参数:通过强转后的对象调用
getActualTypeArguments
,得到泛型参数数组。 - 遍历处理:循环泛型参数数组,用
getTypeName
获取并输出 具体类型名
4.获取方法参数上的泛型信息
总结
场景 | 获取泛型类型的关键 API | 说明 |
---|---|---|
字段泛型 | Field.getGenericType() | 针对单个字段的泛型解析 |
接口泛型 | Class.getGenericInterfaces() | 返回所有接口的泛型类型数组 |
父类泛型 | Class.getGenericSuperclass() | 返回直接父类的泛型类型 |
自身类泛型 | Class.getTypeParameters() | TypeVariable[] | 类定义时声明的泛型变量(如 class MyClass<T> 中的 T ) |