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) 编辑 收藏 举报