例如: 假設此時有一個User類,那么要獲取該User類的真實類型的話,可以直接使用類名+".class"獲取: ”User.class“
或者,通過User類的實例 user.getClass() 來獲取;
上面兩個例子是已經確定該類的類型是User類型了,所以,才可以使用上面的方法。
而泛型類因為還不能確定是什么類型,所以沒辦法使用上面的兩個方法(實例.getClass(),類名.class);
如果類是泛型的話,那么該如何獲取呢?
我們可以通過獲取該泛型類的子類的傳入的類型參數來確定該泛型類的真實類型。
如:
有個類繼承了一個泛型類,給該泛型類傳入了一參數 "User" --->這個參數就是解決問題的關鍵點了
public UserDao extends BaseDaoImpl<User>{
.....
}
該泛型類BaseDaoImpl<T>的代碼如下:
public BaseDaoImpl() {
Class c = this.getClass();
Type t = c.getGenericSuperclass();
if (t instanceof ParameterizedType) {
// System.out.println("in if");
Type[] p = ((ParameterizedType) t).getActualTypeArguments();
// System.out.println(Arrays.toString(p));
this.clazz = (Class<T>) p[0];
}
}
BaseDaoImpl<T>的構造函數中的 this 指的是子類的實例。
this.getClass()獲取子類的真實類型;
c.getGenericSuperclass(); 獲取泛型父類
t.getActualTypeArguments(); 通過該泛型父類來獲取真實的類型參數的數組;也就是獲取泛型父類的尖括號里面的參數<T>,
因為泛型的尖括號是可以有多個參數的,所以該方法返回的是一個數組。
p[0](既:t.getActualTypeArguments()[0]); 獲取該數組的第一個值。因為我們知道在該例子中BaseDaoImpl<T>只有一個參數T。所以我們只需要獲取第一個值就可以了。
在這里需要注意的是:
范式應該在編譯的時候就指定,而不是運行時。
如果我把上面BaseDaoImpl(){ }改成如下這樣子:
[錯誤示范]
public BaseDaoImpl() {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
//輸出結果,驗證類型名稱是否正確
//System.out.println("clazz --> " + clazz.getSimpleName()); //getSimpleName()是返回不包含包名的類名稱
}
上面這段代碼,因為在編譯器進行編譯的時候,還不能確定泛型的具體類型,所以會報如下的錯誤:
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
==================================
==================================
結束。