You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.5 KiB
100 lines
2.5 KiB
问题:Java泛型擦除后如何通过反射获取泛型信息?
|
|
答:虽然 Java 在编译时会进行类型擦除(Type Erasure),将泛型替换为原始类型(通常是 Object 或边界类型),但某些情况下泛型信息会被保留在字节码中,可以通过反射获取:
|
|
|
|
1. 获取父类/接口的泛型参数
|
|
Java
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
16
|
|
17
|
|
18
|
|
19
|
|
20
|
|
21
|
|
22
|
|
23
|
|
import java.lang.reflect.ParameterizedType;
|
|
import java.lang.reflect.Type;
|
|
import java.util.List;
|
|
|
|
// 继承泛型类时指定具体类型
|
|
public class StringList extends ArrayList<String> {}
|
|
|
|
public class GenericReflectionDemo {
|
|
public static void main(String[] args) {
|
|
// 获取父类的泛型参数
|
|
Class<?> clazz = StringList.class;
|
|
Type genericSuperclass = clazz.getGenericSuperclass();
|
|
|
|
if (genericSuperclass instanceof ParameterizedType) {
|
|
ParameterizedType pt = (ParameterizedType) genericSuperclass;
|
|
Type[] actualTypeArgs = pt.getActualTypeArguments();
|
|
for (Type type : actualTypeArgs) {
|
|
System.out.println("泛型参数类型: " + type);
|
|
// 输出: class java.lang.String
|
|
}
|
|
}
|
|
}
|
|
}
|
|
2. 获取字段的泛型类型
|
|
Java
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
public class GenericField {
|
|
private List<String> names;
|
|
private Map<Integer, String> mapping;
|
|
}
|
|
|
|
// 获取字段泛型
|
|
Field field = GenericField.class.getDeclaredField("names");
|
|
Type genericType = field.getGenericType();
|
|
if (genericType instanceof ParameterizedType) {
|
|
ParameterizedType pt = (ParameterizedType) genericType;
|
|
System.out.println("字段泛型参数: " +
|
|
Arrays.toString(pt.getActualTypeArguments()));
|
|
// 输出: [class java.lang.String]
|
|
}
|
|
3. 获取方法参数的泛型类型
|
|
Java
|
|
1
|
|
2
|
|
3
|
|
4
|
|
public void process(List<String> items, Map<K, V> map) {}
|
|
|
|
Method method = clazz.getMethod("process", List.class, Map.class);
|
|
Type[] paramTypes = method.getGenericParameterTypes();
|
|
4. 核心 API 总结
|
|
反射方法 用途
|
|
getGenericSuperclass() 获取父类的泛型类型
|
|
getGenericInterfaces() 获取接口的泛型类型
|
|
Field.getGenericType() 获取字段的泛型类型
|
|
Method.getGenericReturnType() 获取返回值的泛型类型
|
|
Method.getGenericParameterTypes() 获取方法参数的泛型类型
|
|
ParameterizedType.getActualTypeArguments() 获取实际泛型参数
|
|
⚠️ 限制:局部变量和方法参数的泛型信息在运行时是完全擦除的,无法通过反射获取。
|
|
|