首页 > 其他 > 详细

反射和泛型(二)

时间:2020-02-19 16:58:34      阅读:42      评论:0      收藏:0      [点我收藏+]

转载自https://blog.csdn.net/u012466482/article/details/78429979

我们知道,一个Java的类主要包括两个元素,即是成员变量和成员方法。成员变量包括实例成员变量和静态成员变量,而成员方法也有实例成员方法和静态成员方法,构造方法则是特殊的成员方法。而反射的主要作用是能够在运行时获取一个Class的各个元素的结构,但无法更改这些元素的结构。这些元素就是前面说的成员变量和成员方法,并且对于成员变量,反射可以对其进行设值和取值,对于成员方法,反射可以直接对其进行方法调用,而对于特殊的成员方法构造方法而言,反射可以调用构造方法元素的newInstance()方法直接实例化一个该类的对象,而不需要使用new的方式。

那么现在问题来了,在使用反射获取一个Class的各个元素的结构时,哪些地方可以直接获取得到泛型类型参数,并且能够将该泛型类型参数直接实例化成一个对象呢?

在对反射进行研究后发现,有以下三种情况可以实现:
一. 成员变量类型的泛型参数。
二. 成员方法返回值的泛型参数。
三. 成员方法参数类型的泛型参数,包括构造方法。

在说到泛型类型参数时,要先说一下Type接口,Type接口只有一个实现类Class,但是有四个子接口,这四个Type子接口描述了Java泛型的四种形式。分别是:

GenericArrayType 该接口表示一种数组类型,其组件类型为参数化类型或类型变量,如参数化类型数组Map<String, Date>[] mapArr,还有类型变量数组T[] tArr

ParameterizedType 该接口表示参数化类型,如 Collection<String>。

TypeVariable<D>  该接口是各种类型变量的公共高级接口,可以表示泛型声明的参数类型(不存在的类型),如 class ClassName<T>和Collection<T>,这里的T就是一个类型变量。

WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。

在Java泛型的这四种形式中,类型变量和类型变量数组还有通配符类型表达式都是取不到泛型参数的实际类型的,只有泛型的参数化类型和参数化类型数组中的实际类型可以得到实际类型,并可用于实例化,也就是说只有前两种情况GenericArrayTypeParameterizedType才有可能得到泛型的实际类型。

一. 成员变量类型的泛型参数。
Field类下有个Type getGenericType()方法可以获取泛型类,返回类型为Type,代码如下:

Type type = field. getGenericType();

二. 成员方法返回值的泛型参数。
Method类下有个Type getGenericReturnType()方法可以获取成员方法返回值的泛型类,返回类型为Type,代码如下:

Type type = method. getGenericReturnType();

三.  Method类下有个Type[] getGenericParameterTypes()方法可以获得成员方法各个参数的泛型类的数组,返回值为Type[],(Constructor类里面也有一个getGenericParameterTypes()方法,也可以使用相同的方式取到构造器参数里的实际泛型参数)代码如下:

Type[] typeArr = method. getGenericParameterTypes();

 

在第一步得到的Type类型的对象后,这个对象有可能是Type接口的四个子接口实现类的实例。在使用测试代码测试后发现,这个对象只会是GenericArrayType和ParameterizedType两个接口的实现类的实例。此处往下没有再转载

 

得到type类型之后,如果获取具体的泛型类型

public class Generic {
    /**
     * 方法一
     * @param map
     * @param list
     */
    public static void test01(Map<String,String>map,List<String>list){
        System.out.println("Generic.test01()");
    }
    /**
     * 方法二
     * @return
     */
    public Map<Integer,String>test02(){
        System.out.println("Generic.test02()");
        return null;
    }

    public static void main(String[] args) {
        try {

            Method m = Generic.class.getMethod("test01", Map.class,List.class);
            Type [] t = m.getGenericParameterTypes();//获取参数泛型
            for(Type paramType:t){
                System.out.println("#"+paramType);
                if(paramType instanceof ParameterizedType){
                    Type[]genericTypes = ((ParameterizedType)paramType).getActualTypeArguments();
                    for(Type genericType:genericTypes){
                        System.out.println("泛型类型"+genericType);
                    }
                }
            }

            Method m2 =Generic.class.getMethod("test02", null);
            Type returnType = m2.getGenericReturnType();//获取返回类型的泛型
            if(returnType instanceof ParameterizedType){
                Type [] genericTypes2 =((ParameterizedType)returnType).getActualTypeArguments();
                for(Type genericType2:genericTypes2){
                    System.out.println("返回值,泛型类型"+genericType2);
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

#java.util.Map<java.lang.String, java.lang.String>   -->它对应Type [] t = m.getGenericParameterTypes()
泛型类型class java.lang.String  --->它对应Type[]genericTypes = ((ParameterizedType)paramType).getActualTypeArguments();
泛型类型class java.lang.String
#java.util.List<java.lang.String>
泛型类型class java.lang.String
返回值,泛型类型class java.lang.Integer
返回值,泛型类型class java.lang.String

 

反射和泛型(二)

原文:https://www.cnblogs.com/chxyshaodiao/p/12331697.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!