java在運行時獲取泛型實例的方法

如題,有時候我們在接口中或者是抽象類使用泛型來適應子類不同的類型,可是當我們需要拿到泛型實例或者泛型類型的時候,可以這樣去得到:

抽象類和接口各不相同。

  • 抽象類獲取泛型實例的方法
Class<?> aClass = obj.getClass();//先得到類的字節碼
Type genericSuperclass = aClass.getGenericSuperclass();// 返回超類的type
ParameterizedType types = (ParameterizedType) genericSuperclass;// 如果超類是參數化類型,返回的Type對象必須準確地反映源代碼中使用的實際類型參數,也就是 ParameterizedType 類型
Type[] actualTypeArguments =  types.getActualTypeArguments();//返回表示此類型的實際類型參數的Type對象的數組。請注意,在某些情況下,返回的數組是空的。如果此類型表示嵌套在參數化類型中的非參數化類型,則會發生這種情況。
Class<T> reponseClass = (Class) actualTypeArguments[0];
  • 接口獲取泛型實例的方法
Class<?> aClass = obj.getClass();//先得到類的字節碼
/*
返回表示由此對象表示的類或接口直接實現的接口的類型。
如果超級接口是一個參數化類型,返回的Type對象必須準確地反映源代碼中使用的實際類型參數。代表每個超級界面的參數化類型是在之前沒有創建的情況下創建的。有關參數化類型的創建過程的語義,請參閱ParameterizedType的聲明。
如果此對象表示一個類,則返回值是一個包含表示由類實現的所有接口的對象的數組。數組中接口對象的順序對應于該對象表示的類的聲明的implements子句中的接口名稱的順序。在數組類中,接口Cloneable和Serializable按照這個順序返回。
如果此對象表示一個接口,則該數組包含表示由該接口直接擴展的所有接口的對象。數組中接口對象的順序對應于該對象表示的接口聲明的extends子句中接口名稱的順序。
如果此對象表示不實現接口的類或接口,則該方法返回長度為0的數組。
如果這個對象表示一個原始類型或void,則該方法返回一個長度為0的數組。
* */
Type[] types = aClass.getGenericInterfaces();
ParameterizedType parameterizedType = (ParameterizedType) types[0];
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Class<T> reponseClass = (Class) actualTypeArguments[0];

最后附上完整工具類代碼:

/**
 * 運行時獲取泛型類型
 */
public class GenericUtil {
    public static <T> T getSuperclassType(Object obj, int i) {
        try {
            Class<?> aClass = obj.getClass();//先得到類的字節碼
            Type genericSuperclass = aClass.getGenericSuperclass();
            if (genericSuperclass instanceof ParameterizedType) {
                ParameterizedType types = (ParameterizedType) genericSuperclass;//抽象類
                Type[] actualTypeArguments = types.getActualTypeArguments();
                Class<T> reponseClass = (Class) actualTypeArguments[i];
                return reponseClass.newInstance();
            } else {
                return null;
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T getInterfaceType(Object obj, int i) {
        try {
            Class<?> aClass = obj.getClass();//先得到類的字節碼
                /*
                返回表示由此對象表示的類或接口直接實現的接口的類型。
                如果超級接口是一個參數化類型,返回的Type對象必須準確地反映源代碼中使用的實際類型參數。代表每個超級界面的參數化類型是在之前沒有創建的情況下創建的。有關參數化類型的創建過程的語義,請參閱ParameterizedType的聲明。
                如果此對象表示一個類,則返回值是一個包含表示由類實現的所有接口的對象的數組。數組中接口對象的順序對應于該對象表示的類的聲明的implements子句中的接口名稱的順序。在數組類中,接口Cloneable和Serializable按照這個順序返回。
                如果此對象表示一個接口,則該數組包含表示由該接口直接擴展的所有接口的對象。數組中接口對象的順序對應于該對象表示的接口聲明的extends子句中接口名稱的順序。
                如果此對象表示不實現接口的類或接口,則該方法返回長度為0的數組。
                如果這個對象表示一個原始類型或void,則該方法返回一個長度為0的數組。
                * */
            Type[] types = aClass.getGenericInterfaces();
            ParameterizedType parameterizedType = (ParameterizedType) types[0];
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            Class<T> reponseClass = (Class) actualTypeArguments[i];
            return reponseClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Class<?> forName(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • Kotlin 知識梳理系列文章 Kotlin 知識梳理(1) - Kotlin 基礎Kotlin 知識梳理(2) ...
    澤毛閱讀 2,570評論 0 4
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,142評論 0 62
  • 在經過一次沒有準備的面試后,發現自己雖然寫了兩年的android代碼,基礎知識卻忘的差不多了。這是程序員的大忌,沒...
    猿來如癡閱讀 2,872評論 3 10
  • 接口/抽象類意義規范、擴展、回調為其子類提供一個公共的類型 封裝子類中得重復內容 定義抽象方法,子類雖然有不同的實...
    MigrationUK閱讀 2,201評論 1 28