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

问题: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() 获取实际泛型参数
⚠️ 限制:局部变量和方法参数的泛型信息在运行时是完全擦除的,无法通过反射获取。