学习Java 泛型 Type体系

最近在看retrofit2源码,框架的大致原理就是在okhttp的基础上利用注解和动态代理自动生成okhttp的request,抽象地理解就是利用注解表示请求体。在源码中看到里面有很多Java泛型,通过反射去获取泛型信息。如果说要看懂反射的泛型代码,那必须对泛型有足够的了解,其中Java 泛型 Type体系可是重中之重。

Type体系中Type接口是最顶层接口,用于表示JAVA的类型,包括 raw types(声明的类型), parameterized types(参数化类型), array types(范型数组), type variables (类型变量)and primitive types(基本类型)。其中primitive types是指基本类型, 包括boolean, byte, short, int, long,char, float,double,注意不包括String类型。

Type的直接继承子接口有四个:
ParameterizedType (参数化类型)
TypeVariable(类型变量)
GenericArrayType(范型数组)
WildcardType(通配符的类型)

UML如图所示

Java Type 继承体系

一、ParameterizedType (参数化类型)
形如 Collection<String> 或者Map<String,User> map声明的类型
接口方法:
Type[] getActualTypeArguments();
获取泛型中的参数,声明如Map<String,User> map 拿到String,User这两个参数的类型
Type getRawType();
获取声明的原始类型,如Map<String,User> map 拿到的是Map类型
Type getOwnerType();
获取所属类型,如Map.Entry<String, String > entry; 拿到的是Map类型,如果没有则返回null

测试代码:

public class TestType {


    public static void main(String[] args) {


        testParameterizedType();

//        testTypeVariable();

//        testGenericArrayType();

//        testWildCardType();


    }
  public static class TestParameterizedBean {


        // 下面的 field 的 Type 属于 ParameterizedType
        Map<String, TestParameterizedBean> map;
        Set<String> set1;
        Class<?> clz;
        Holder<String> holder;
        List<String> list;
        // Map<String,TestParameterizedBean> map 这个            ParameterizedType 的 getOwnerType() 为 null,
        // 而 Map.Entry<String, String> entry 的 getOwnerType() 为 Map 所属于的 Type。
        Map.Entry<String, String> entry;
        // 下面的 field 的 Type 不属于ParameterizedType
        String str;
        Integer i;
        Set set;
        List aList;
    }


    public static void testParameterizedType() {
        Field f = null;
        try {
            Field[] fields = TestParameterizedBean.class.getDeclaredFields();
            // 打印出所有的 Field 的 TYpe 是否属于 ParameterizedType
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                System.out.println(f.getName()+" type is "+f.getGenericType().getTypeName());
                System.out.println(
                         "------- is ParameterizedType ?  "
                        + (f.getGenericType() instanceof ParameterizedType));

                if (f.getGenericType() instanceof ParameterizedType) {
                    ParameterizedType pType = (ParameterizedType) f.getGenericType();
                    System.out.println("------- rawType is " + pType.getRawType());

                    //获取泛型的声明参数   Map<T,K>  map; 则getActualTypeArguments()是拿到T,k组成的数组
                    //getRawType() 则是interface java.util.Map
                    //getOwnerType()如 Map.Entry<String, String> entry;则拿到的是interface java.util.Map
                    for (Type type : pType.getActualTypeArguments()) {
                        System.out.println("------- getActualTypeArguments  is " + type);
                    }
                    System.out.println("------- getOwnerType() is " + pType.getOwnerType()); // null
                }


            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

输出结果:

map type is java.util.Map<java.lang.String, main.TestType$TestParameterizedBean>
------- is ParameterizedType ?  true
------- rawType is interface java.util.Map
------- getActualTypeArguments  is class java.lang.String
------- getActualTypeArguments  is class main.TestType$TestParameterizedBean
------- getOwnerType() is null
set1 type is java.util.Set<java.lang.String>
------- is ParameterizedType ?  true
------- rawType is interface java.util.Set
------- getActualTypeArguments  is class java.lang.String
------- getOwnerType() is null
clz type is java.lang.Class<?>
------- is ParameterizedType ?  true
------- rawType is class java.lang.Class
------- getActualTypeArguments  is ?
------- getOwnerType() is null
holder type is javax.xml.ws.Holder<java.lang.String>
------- is ParameterizedType ?  true
------- rawType is class javax.xml.ws.Holder
------- getActualTypeArguments  is class java.lang.String
------- getOwnerType() is null
list type is java.util.List<java.lang.String>
------- is ParameterizedType ?  true
------- rawType is interface java.util.List
------- getActualTypeArguments  is class java.lang.String
------- getOwnerType() is null
entry type is java.util.Map.java.util.Map$Entry<java.lang.String, java.lang.String>
------- is ParameterizedType ?  true
------- rawType is interface java.util.Map$Entry
------- getActualTypeArguments  is class java.lang.String
------- getActualTypeArguments  is class java.lang.String
------- getOwnerType() is interface java.util.Map
str type is java.lang.String
------- is ParameterizedType ?  false
i type is java.lang.Integer
------- is ParameterizedType ?  false
set type is java.util.Set
------- is ParameterizedType ?  false
aList type is java.util.List
------- is ParameterizedType ?  false

二、TypeVariable(类型变量)
如声明为T t 的变量,其中T在class中声明定义

接口方法:
Type[] getBounds();
得到上边界的 Type数组,如类为TypeVariableBean< extends InputStream & Closeable, V>,则返回的是 K 的上边界数组 InputStream 和 Serializable。 V 没有指定的话, 默认上边界是 Object
D getGenericDeclaration();
返回的是声明这个 Type 所在的类 的 Type
String getName();
返回Type的名字
AnnotatedType[] getAnnotatedBounds();
返回注解类型的上边界数组,与getBounds()类似

测试代码:

public class TestType {


    public static void main(String[] args) {


//        testParameterizedType();

        testTypeVariable();

//        testGenericArrayType();

//        testWildCardType();


    }
   private static void testTypeVariable() {
        TypeVariableBean bean = new TypeVariableBean<FileInputStream, String>();

        Field[] fields = bean.getClass().getDeclaredFields();
        // 打印出所有的 Field 的 TYpe 是否属于 TypeVariable
        Field f = null;
        for (int i = 0; i < fields.length; i++) {
            f = fields[i];
            System.out.println(f.getName()
                    + "   is TypeVariable ?  "
                    + (f.getGenericType() instanceof TypeVariable));

            if (f.getGenericType() instanceof TypeVariable) {

                TypeVariable typeVariable = (TypeVariable) f.getGenericType();
                System.out.println(typeVariable.getGenericDeclaration() + " TypeVariable");
                System.out.println("边界类型:");
                for (Type t : typeVariable.getBounds()) {
                    System.out.println( t.getTypeName());
                }
            }
        }

    }
      public static class TypeVariableBean<K extends InputStream & Closeable, V> {
        // K 的上边界是 InputStream
        K key;//TypeTypeVariable
        // 没有指定的话 ,V 的 上边界 属于 Object
        V value;//TypeTypeVariable

        // 不属于 TypeTypeVariable
        V[] values; //GenericArrayType
        String str;// PrimitiveType
        List<K> kList;//ParameterizedType

    }

}

输出结果

key the type is K
-------  is TypeVariable ?  true
-------GenericDeclaration is class main.TestType$TypeVariableBean
-------边界类型:
------- java.io.InputStream
------- java.io.Closeable
value the type is V
-------  is TypeVariable ?  true
-------GenericDeclaration is class main.TestType$TypeVariableBean
-------边界类型:
------- java.lang.Object
values the type is V[]
-------  is TypeVariable ?  false
str the type is class java.lang.String
-------  is TypeVariable ?  false
kList the type is java.util.List<K>
-------  is TypeVariable ?  false

三、GenericArrayType(范型数组)
变量声明形如的T[] genericArray; 或者List<String>[] array 的类型
接口方法
Type getGenericComponentType();
获取泛型数组中的元素的类型
测试代码

public class TestType {


    public static void main(String[] args) {


//        testParameterizedType();

//        testTypeVariable();

        testGenericArrayType();

//        testWildCardType();


    }
     //GenericArrayType测试
    // 简单来说就是:范型数组,组成数组的元素中有范型则实现了该接口;
    // 它的组成元素是 ParameterizedType 或 TypeVariable 类型
  public static class GenericArrayTypeBean<T> {

        // 属于 GenericArrayType
        List<String>[] pTypeArray;//组成元素是ParameterizedType类型的List<String>
        // 属于 GenericArrayType
        T[] vTypeArray;//组成元素是 TypeVariable 类型的T
        // 不属于 GenericArrayType
        List<String> list;//ParameterizedType类型
        // 不属于 GenericArrayType
        String[] strings;//正常类型
        // 不属于 GenericArrayType
        int[] ints;//正常类型

    }

    public static void testGenericArrayType() {
        Field[] fields = GenericArrayTypeBean.class.getDeclaredFields();
        Field f = null;
        for (int i = 0; i < fields.length; i++) {
            f = fields[i];
            System.out.println(f.getName() + " the type is " + f.getGenericType());
            System.out.println(
                    "--------   is GenericArrayType ?  "
                    + (f.getGenericType() instanceof GenericArrayType));

            if (f.getGenericType() instanceof GenericArrayType) {

                GenericArrayType type = (GenericArrayType) f.getGenericType();
                //getGenericComponentType()是获取泛型数组中的元素的类型
                System.out.println("--------数组元素是  "+type.getGenericComponentType().getTypeName());

            }
        }

    }
 }

输出结果:

pTypeArray the type is java.util.List<java.lang.String>[]
--------   is GenericArrayType ?  true
--------数组元素是  java.util.List<java.lang.String>
vTypeArray the type is T[]
--------   is GenericArrayType ?  true
--------数组元素是  T
list the type is java.util.List<java.lang.String>
--------   is GenericArrayType ?  false
strings the type is class [Ljava.lang.String;
--------   is GenericArrayType ?  false
ints the type is class [I
--------   is GenericArrayType ?  false

四、WildcardType(通配符的类型)
参数声明中包含?通配符的类型。如List<?>,List<? extends Number>,List<? super Number> 这些类型 都属于WildcardType
extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null.

接口方法:
Type[] getUpperBounds();
得到上边界 Type 的数组,如List<? extends Number>,返回的上边界Type是数组 是 {Number全类名}
Type[] getLowerBounds();
得到下边界 Type 的数组,如List<? super Number> ,返回的是下边界数组是{Number全类名}

默认情况下没有指定的话,上边界默认是 Object ,下边界是空。

测试代码

public class TestType {


    public static void main(String[] args) {


//        testParameterizedType();

//        testTypeVariable();

//        testGenericArrayType();

        testWildCardType();


    }
       public static void testWildCardType() {
        try {

            Field[] fields = WildcardTypeBean.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                Type type = field.getGenericType();


                String nameString = field.getName();
                System.out.println(nameString + " the type is " + field.getGenericType());

                if (!(type instanceof ParameterizedType)) {
                    System.out.println("-----不是ParameterizedType类型,没有通配符");
                    continue;
                }
                System.out.println("-----获取声明参数");
                ParameterizedType parameterizedType = (ParameterizedType) type;
                //获取声明参数
                type = parameterizedType.getActualTypeArguments()[0];
                System.out.println("-----声明参数getActualTypeArguments()[0] type is  "+parameterizedType.getTypeName());
                if (!(type instanceof WildcardType)) {
                    System.out.println("-----不是WildcardType");
                    continue;
                }
                WildcardType wildcardType = (WildcardType) type;
                Type[] lowerTypes = wildcardType.getLowerBounds();
                if (lowerTypes != null) {
                    System.out.println("-----下边界");
                    if (lowerTypes != null) {
                        for (Type t :
                                lowerTypes) {
                            System.out.println("-----"+t.getTypeName());
                        }

                    }
                }
                Type[] upTypes = wildcardType.getUpperBounds();
                if (upTypes != null) {
                    System.out.println("-----上边界:");
                    for (Type t : upTypes) {
                        System.out.println("-----"+t.getTypeName());
                    }

                }
                System.out.println("---------------------------");

            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
 public static class WildcardTypeBean {

        private List<? extends Number> a;  // a没有下界,
        //  没有指定的话,上边界默认是 Object ,下边界是  String
        private List<? super String> b;

        private List<String> c;//类型参数中没有WildcardType类型

        private Class<?> aClass;//默认有上边界 Object,无默认下边界
    }

}

输出结果

a the type is java.util.List<? extends java.lang.Number>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is  java.util.List<? extends java.lang.Number>
-----下边界
-----上边界:
-----java.lang.Number
---------------------------
b the type is java.util.List<? super java.lang.String>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is  java.util.List<? super java.lang.String>
-----下边界
-----java.lang.String
-----上边界:
-----java.lang.Object
---------------------------
c the type is java.util.List<java.lang.String>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is  java.util.List<java.lang.String>
-----不是WildcardType
aClass the type is java.lang.Class<?>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is  java.lang.Class<?>
-----下边界
-----上边界:
-----java.lang.Object
---------------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值