由于类型擦除,java 中的泛型对象在运行时是不知道自己类型参数的类型的。
但有几种特殊情况,能够获取泛型对象的参数类型:
1、类中有 class 信息(类中有一个 Class 字段)
2、父类中有 class 信息(父类是泛型类,并指定了参数类型)
3、持有者中有 class 信息(是一个类的 Field、Method)
一、类中有 class 信息
类声明:
static class A1<T> {
public Class<T> mClass;
public A1(Class<T> aClass) {
mClass = aClass;
}
}
使用:
A1<String> a1 = new A1<>(String.class);
System.out.println(a1.mClass);
输出:
class java.lang.String
二、父类中有 class 信息
2.1 子类
类声明:
static class A2 extends A2Parent<String> {
}
static class A2Parent<T> {
}
使用:
A2 a2 = new A2();
printClass(a2);
public static void printClass(Object o) {
System.out.println();
format("o: ", o);
format("class: ", o.getClass());
format("superClass: ", o.getClass().getSuperclass());
format("genericSuperClass: ", o.getClass().getGenericSuperclass());
format("genericSuperClass typeArgument: ", ((ParameterizedType) o.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
输出:
o: A2@28a418fc
class: class A2
superClass: class A2Parent
genericSuperClass: A2Parent<java.lang.String>
genericSuperClass typeArgument: class java.lang.String
2.2 匿名子类
使用:
A2Parent<String> parent = new A2Parent<String>() {
};
printClass(parent);
输出:
o: $1@5305068a
class: $1
superClass: A2Parent
genericSuperClass: A2Parent<java.lang.String>
genericSuperClass typeArgument: class java.lang.String
三、持有者中有 class 信息
类声明:
static class A3<T> {
}
static class A3User {
A3<String> a3 = new A3<>();
}
使用:
A3User a3User = new A3User();
try {
Field field = FieldUtils.getField(a3User.getClass(), "a3");
System.out.println(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
} catch (Exception e) {
e.printStackTrace();
}
输出:
class java.lang.String