java 编程基础 反射方式获取泛型的类型Fileld.getGenericType() 或Method.getGenericParameterTypes(); (ParameterizedType) ;getActualTypeArguments()

引言

自从JDK5以后,Java Class类增加了泛型功能,从而允许使用泛型来限制Class类,例如,String.class的类型实际上是 Class 如果 Class 对应的类暂时未知,则使 Class<?>。通过在反射中使用泛型,可以避免使用反射生成的对象需要强制类型转换。
泛型作用对比:
如下示例没有使用泛型时,编译不报错,运行时报错强制转换异常
public class HasNoFanxin {
    public static Object newInstance(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clz = Class.forName(className);
        return clz.newInstance();
    }
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        String str = (String) newInstance("java.lang.Date");
        System.out.println(str);
    }
}

如下使用泛型,输入有误的话编译时就会报异常,提前提示错误(编译时就自动推断了泛型的真实类型)

public class HasFanxin {
    public static <T> T newInstance(Class<T> clz) throws InstantiationException, IllegalAccessException {
        return clz.newInstance();
    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        Date str = newInstance(Date.class); // 这里传入什么类型,传出就必须是什么类型,如果写成了String str = ... 就会编译报错
    }
}

通过反射获取变量、方法形参的泛型类型

以获取类变量泛型为例

前提:
通过反射获取类对应的成员变量Field
获取步骤:
1. 获得成员变量的类型
  • Type gType = f.getGenericType();
2. 判断类型是否为带泛型的类型
  • gtype instanceof ParameterizedType
3. 将判断为待泛型的Type对象强制转换为ParameterizedType对象,(ParameterizedType代表被参数化的类型:也就是增加了泛型限制的类型)
  • ParameterizedType ptype = (ParameterizedType) type
4.通过强制转换后的ParameterizedType带泛型对象获取泛型的类型

getRawType() 返回没有泛型信息的原始类型。

getActualTypeArguments(): 返回泛型参数的类型Type 数组。

  • Type[] types = ptype.getActualTypeArguments();

获取方法参数的泛型,可以通过反射方法的参数本身Parameter反射对象,再通过反射对象的getParameterizedType()方法获取本参数的类型的Type对象,进行如上第 2.步骤及以后

或者

通过反射的方法Method对象,通过Method对象getGenericParameterTypes()方法,直接获取所有形参的类型组成的Type数组,再循环经过第 2.步骤及以后

 

package com.zmd.fanxingfanshe;

import java.lang.reflect.*;
import java.util.List;
import java.util.Map;

/**
 * @ClassName FanxingTest
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/17.
 */
public class FanxingTest {
    //带泛型的属性(类变量或实例变量)
    private Map<String, Integer> data;
    private String string;
    //定义带泛型的方法
    private static void fanxingMethod(Map<String, Integer> users, String list){

    }
    //测试获取泛型
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        //获取类
        Class<FanxingTest> cls = FanxingTest.class;
        //获取类变量
        Field dataField = cls.getDeclaredField("data");
        System.out.println("=========获取类变量泛型类型===============");

        //输出data的类型interface java.util.Map
        System.out.println("data 的类型:" + dataField.getType());

        //获取对应的带泛型类型
        Type gtype = dataField.getGenericType();
        System.out.println("参数类型:" + gtype); //java.util.Map<java.lang.String, java.lang.Integer>
        if (gtype instanceof ParameterizedType){
            //将Type对象强制类型转换为ParameterizedType对象
            ParameterizedType ptype = (ParameterizedType) gtype;
            System.out.println(ptype);
            System.out.println(gtype + "的原始类型:" + ptype.getRawType());
            //获取对应的泛型的类型
            Type[] tTypes = ptype.getActualTypeArguments();
            for (Type tType : tTypes){
                System.out.println(tType);
            }
        }


        /**
         * 获取方法形参的泛型
         */
        System.out.println("=========通过反射获取方法,再通过方法getGenericParameterTypes获取形参泛型类型:===============");
        //输入方法名和参数的类列表,获取具体方法的反射
        Method fxMethod = cls.getDeclaredMethod("fanxingMethod", Map.class, String.class);
        //设置private类型方法可访问
        fxMethod.setAccessible(true);
        //获取所有参数类型列表
        Type[] parameterTypes = fxMethod.getGenericParameterTypes();
        for (Type type: parameterTypes){
            //当前参数类型
            System.out.println("参数类型" + type);
            if (type instanceof ParameterizedType){
                ParameterizedType ptype = (ParameterizedType) type;
                //原始类型
                System.out.println("参数原始类型:" + ptype.getRawType());
                //获取对应泛型的类型
                Type[] types = ptype.getActualTypeArguments();
                for (Type tType: types){
                    System.out.println(tType);
                }
            }
        }

        //通过反射参数自身反射泛型
        System.out.println("=========通过反射获取方法,再通过方法获取参数反射,再通过参数.getParameterizedType()获取形参泛型类型:===============");
        Parameter[] parameters = fxMethod.getParameters();
        for (Parameter parameter : parameters){
            System.out.println("获取到参数:" + parameter.getName());
            Type type = parameter.getParameterizedType();
            System.out.println(parameter.getName() + "参数的类型:" + type);
            if (type instanceof ParameterizedType){
                ParameterizedType parameterizedType = (ParameterizedType) type;
                System.out.println(parameter.getName() + "参数的原始类型:"+ parameterizedType.getRawType());
                Type[] types = parameterizedType.getActualTypeArguments();
                for (Type type1 : types){
                    System.out.println(type1);
                }
            }
        }
    }
}

输出

=========获取类变量泛型类型===============
data 的类型:interface java.util.Map
参数类型:java.util.Map<java.lang.String, java.lang.Integer>
java.util.Map<java.lang.String, java.lang.Integer>
java.util.Map<java.lang.String, java.lang.Integer>的原始类型:interface java.util.Map
class java.lang.String
class java.lang.Integer
=========通过反射获取方法,再通过方法getGenericParameterTypes获取形参泛型类型:===============
参数类型java.util.Map<java.lang.String, java.lang.Integer>
参数原始类型:interface java.util.Map
class java.lang.String
class java.lang.Integer
参数类型class java.lang.String
=========通过反射获取方法,再通过方法获取参数反射,再通过参数.getParameterizedType()获取形参泛型类型:===============
获取到参数:arg0
arg0参数的类型:java.util.Map<java.lang.String, java.lang.Integer>
arg0参数的原始类型:interface java.util.Map
class java.lang.String
class java.lang.Integer
获取到参数:arg1
arg1参数的类型:class java.lang.String

Process finished with exit code 0

 

 

 

posted on 2021-05-18 16:00  zhangmingda  阅读(3052)  评论(0编辑  收藏  举报

导航