1. 程式人生 > >通過反射獲得泛型實際型別

通過反射獲得泛型實際型別

通過反射獲得泛型實際型別

1.獲得類的泛型

子類繼承泛型父類,並對泛型進行指定,通過反射獲得指定型別,
1.使用getGenericSuperclass()方法獲得泛型父類
2.判斷是不是引數化型別是的話強轉型別為ParameterizedType
3.使用ParameterizedType的方法getActualTypeArguments()獲得泛型實際型別
程式碼如下

	public
class Demo1<T> { public void study(Map<String, Integer> map, T t,String str){ } /* * 繼承泛型父類並指定String型別 * */ public class Demo2 extends Demo1<String>{ } public static void main(String[] args) { Demo1.Demo2 demo = new Demo1<>().new Demo2
(); //獲得帶有泛型的父類 Type genericSuperclass = demo.getClass().getGenericSuperclass(); //判斷父類是不是引數化的型別,如果是強轉成ParameterizedType if (genericSuperclass instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType)genericSuperclass; //獲得Demo1<String>,<>中的實際型別引數
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); //獲得引數型別 Class<?> clazz = (Class<?>)actualTypeArguments[0]; System.out.println(clazz); } } }

結果:
在這裡插入圖片描述

2.獲得方法引數中的泛型實際型別

方法引數使用了帶有泛型的類如Map<K,V>,獲得泛型的實際型別,程式碼如下:
1.反射獲得對應方法
2.呼叫getGenericParameterTypes()方法獲得方法引數型別集合
3.遍歷集合對ParameterizedType型別引數進行操作
4.使用ParameterizedType的方法getActualTypeArguments()獲得泛型實際型別

public class Demo {
    //一個方法有Map型別和List型別的引數,並指定泛型
    public void study(Map<String, Integer> map, List<String> list){

    }

    public static void main(String[] args) {
        try {
            //通過反射獲得該方法
            Method study = Demo.class.getMethod("study", Map.class, List.class);
            //獲得該方法的所有引數型別
            Type[] genericParameterTypes = study.getGenericParameterTypes();
            for (Type type : genericParameterTypes){
                    System.out.println("##"+ type);
                    //如果引數為引數化的型別進行強轉
                    if (type instanceof ParameterizedType){
                        ParameterizedType parameterizedType = (ParameterizedType)type;
                        //獲得引數化型別中實際引數(Map<String, Integer> 中<>內定義的引數)
                        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                        //遍歷輸出
                        for (Type tt : actualTypeArguments){
                            System.out.println(tt);
                        }
                    }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

執行結果
在這裡插入圖片描述

3.獲得方法返回值中的泛型實際型別

使用getGenericReturnType()方法獲得方法返回值型別,之後的操作和獲得引數返回型別方法類似

public class Demo2 {
    //一個方法的返回型別是Map並指定了泛型型別
    public Map<String, Integer> study(){
        return new HashMap<String,Integer>();
    }

    public static void main(String[] args) {

        try {
            //通過反射獲得該方法
            Method study = Demo2.class.getMethod("study");
            //獲得方法的返回型別
            Type genericReturnType = study.getGenericReturnType();
            System.out.println("###" + genericReturnType);
            ////如果返回值型別為引數化的型別進行強轉
            if (genericReturnType instanceof ParameterizedType){
                ParameterizedType parameterizedType = (ParameterizedType)genericReturnType;
                //獲得引數化型別中實際引數(Map<String, Integer> 中<>內定義的引數)
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                //遍歷輸出
                for (Type type : actualTypeArguments){
                    System.out.println(type);
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}

執行結果

在這裡插入圖片描述

4.獲得萬用字元型別的上下界

先按照獲得引數泛型實際型別的方法獲得萬用字元表示式(? extends T 或?super T),再進行後續操作。
使用WildcardType介面的getUpperBounds()和getLowerBounds()來獲得型別的上下界

public class Demo3 {
    //study方法傳入List類似引數,其中List指定型別上界為Demo3
    public void study(List<? extends Demo3> list){

    }


    public static void main(String[] args) {
        try {
            Method study = Demo3.class.getMethod("study", List.class);
            Type[] genericParameterTypes = study.getGenericParameterTypes();
            //獲得List引數(java.util.List<? extends com.fxl.GenenricReflect.Demo3>)
            Type type = genericParameterTypes[0];
            if (type instanceof ParameterizedType){
                System.out.println(type);
                //獲得List引數中的泛型實際型別(? extends com.fxl.GenenricReflect.Demo3)
                Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
                for (Type mytypes : actualTypeArguments){
                    //判斷是不是WildcardType並強轉
                    if (mytypes instanceof WildcardType){
                        WildcardType wt = (WildcardType)mytypes;
                        //獲得型別的上界(class com.fxl.GenenricReflect.Demo3)
                        Type[] upperBounds = wt.getUpperBounds();
                        System.out.println(upperBounds[0]);
                    }
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

執行結果
在這裡插入圖片描述
個人筆記,如有錯誤還望指出