欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java如何獲得泛型類中的泛型類型T.class

 更新時間:2024年12月14日 15:37:05   作者:nvd11  
獲取泛型符號E的Class對象的方法,1.反射方案利用匿名子類實例化,但該方法有特殊限制,2.反射方案2直接指定泛型類型,但不靈活,3.構(gòu)造方法方案在初始化時傳入泛型類,但有寫錯風險

Java獲得泛型類的泛型類型T.class

假如我們寫了1個泛型類MyBase

public class MyBase<E> {
    public MyBase(){
        
    }

    public Class<?> getEClass() {
		?
    }   
}

我想寫1個getEClass 的方法, 獲取泛型符號E的Class對象。

直接用E.class E.getClass()都是不合法的, 因為E只是個符號, 沒有被實例化。

1. 反射方案

各種google 各種Stackoverflow 后, 找到利用反射的1個方法。

public class MyBase<E> {
    public MyBase(){
        
    }

    public Class<?> getEClass() {
        
        //get the Class object of this own class 
        Class<? extends MyBase> thisClass = this.getClass();

        //get the Type Object of supper class
        Type superClassType = thisClass.getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType)superClassType;

        //get the Generic Type array
        Type[] genTypeArr = pt.getActualTypeArguments();
        Type genType = genTypeArr[0];
        if (false == genType instanceof Class){
            return Object.class;
        }

        return (Class<Object>) genType;
    }
}

這個方法被測試過, 但是有個很特別的限制,

一定要實例化匿名子類才有效果。

例如:

   @Test
    void testMyBase() {
        MyBase<String> mybase = new MyBase<String>(){};
        log.info("E class is {}",mybase.getEClass());
    }

注意new MyBase(){} 后面的大括號, 意思不是實例化MyBase對象, 而是實例化MyBase的匿名子類。

如果我們寫多1個具體的子類MyList

public class MyList<E> extends MyBase<E> {
    public MyList(){

	}
}

測試方法:

   @Test
    void testGetEClass() {
        MyList<String> mylist = new MyList<String>();
        log.info("E class is {}",mylist.getEClass());
    }

同樣不行, 原因是

		//get the Type Object of supper class
        Type superClassType = thisClass.getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType)superClassType;

這里 我們只能通過本類的Class對象去獲得1個父類 ParameterizedType (包括泛型參數(shù)列表的Type)

而JDK本身只提供了getGenericSuperclass()方法去獲得父類的Type 對象

但是沒有提供例如getGenericClass() 去獲取本類的Type對象…

所以一旦我們不實用匿名子類

當下面代碼被執(zhí)行時

MyList<String> mylist = new MyList<String>();
log.info("E class is {}",mylist.getEClass());

thisClass.getGenericSuperclass() 會獲得MyList的父類MyBase的Type, 問題是MyBase沒有被實例化, 所以pt.getActualTypeArguments()[0] 只會返回E

本身 就return null了

但是如果我們利用匿名子類的化

當下面代碼被執(zhí)行時

MyList<String> mylist = new MyList<String>(){};
log.info("E class is {}",mylist.getEClass());

mylist 的類實際上是1個匿名子類MyList$1, 它的父類就是MyList, 而匿名子類的父類在JVM實際上是被實例化的

所以pt.getActualTypeArguments()[0] 會返回泛型具體類String 的Class。

2. 反射方案2

匿名子類畢竟有點奇怪。

如果避免使用你匿名子類, 我們還有1個辦法

public class MySet extends MyBase<String> {
    public MySet(){
  
    }
}

如上面這個MySet類, 它直接繼承MyBase時指定了具體泛型, 令到自己本身不是1個泛型類。

這樣的話, 不用匿名子類也一樣可以獲得泛型具體類型。

因為這種情況下, 一旦實現(xiàn)MySet, 因為MySet指定了繼承泛型的具體類型, 在JVM 中MyBase也會被實例化。

但是這個方案一樣不好, 不靈活是其次, 我都會指定了具體泛型類型了, 何必用再用getEClass()去獲得泛型具體類型? 多次一舉

  @Test
    void testGetEClass2() {
        MySet myset = new MySet();
        log.info("Set E class is {}",myset.getEClass());
    }

3. 構(gòu)造方法方案

這也是外網(wǎng)強烈推薦的方案

public class MyMap<E> {

    private Class<E> eClass;

    public MyMap(Class<E> eClass){
        this.eClass = eClass;
    }

    public Class<E> getEClass(){
        return this.eClass;
    }

}

讓開發(fā)人員在初始化時,順便外部傳入泛型的類, 不過手抖寫錯的風險…

測試方法:

  @Test
    void testGetEClass3() {
        MyMap<String> myMap= new MyMap<>(String.class);
        log.info("Set E class is {}",myMap.getEClass());
    }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論