由於類型擦除,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