1.Type类型详解

1.Type类型

1.1 什么是Type?

Type是一个空接口,是所有类型的公共接口(父接口),其意义表示Java所有类型。这里所谓的类型是从Java整个语言角度来看的,比如原始类型、参数化类型(泛型)、类型变量及其数组等,可以理解为,Class(类)是Java对现实对象的抽象,而Type是对Java语言对象的抽象。

Type的实现类型,所有Type一共可以表示以下这5类数据。主要介绍的就是四个子接口。
实现了Type接口的子接口为

  • GenericArrayType(泛型数组类型),
  • ParmeterizedType(参数化类型),
  • TypeVariable(类型变量),
  • WildcardType(通配符类型)。

实现了Type接口的子类

  • Class(类)。

1.2 Type的用处

由于java1.5引入了泛型这一概念,大大方便了我们代码的编写和优化,但是考虑到泛型擦除这一问题,当我们的代码在运行时期会擦除所有的泛型,这一我们在运行时期想要获取某一类原来是带有泛型的,而后来被擦除了的数据的泛型类型时就会有问题。所以java引入了Type这一概念。Type也主要是为在运行时期获取泛型而服务。

1.3 ParmeterizedType(参数化类型)的作用

ParmeterizedType主要是用来表示 如 Collection或者Class。 ParmeterizedType表示的类型非常的简单,只要带着泛型,除了不可以是数组和本类上定义的泛型以外,其他都被列入ParameterizedType的范围。
ParameterizedType表示的是参数化类型,例如List、Map<Integer,String>、Service这种带有泛型的类型。

ParameterizedType接口中常用的方法有三个,分别是:

   Type getRawType() 返回参数化类型中的原始类型,例如List<String>的原始类型为List

   Type[] getActualTypeArguments() 获取参数化类型的类型变量或者是实际类型列表,例如Map<Integer, String>的实际泛型列表Integer和String。改列表的所有类型都是Type,也即是说,可能存在多层嵌套的情况。

   Type getOwnerType() 返回是类型所属的类型,例如存在A<T>,其中定义了内部类InnerA<T>,则InnerA<T>的所属类型是A<T>,如果是顶层类型则返回null,这种关系比较常见的是Map<K, V>接口与Map.Entry<K, V>接口,Map<K,V>接口是Map.Entry<K,V>接口的ownerType。

1.3.1 测试ParmeterizedType

 @Test
    public void test() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<TypeBean> bean = (Class<TypeBean>) Class.forName("com.noahgroup.supervise.TypeBean");
        Field[] declaredFields = bean.getDeclaredFields();
        int i = 1;
        for (Field field : declaredFields) {
            field.setAccessible(true);
            System.out.println("--------------" + i + "---------------");
            System.out.println("field name is : " + field.getName());
            System.out.print("field.getGenericType() instanceof ParameterizedType");
            System.out.println("--------" + (field.getGenericType() instanceof ParameterizedType));
            if (field.getGenericType() instanceof ParameterizedType) {
                ParameterizedType type = (ParameterizedType) field.getGenericType();
                System.out.println("---------------ActualTypeArguments:---------------");
                //获取范型的参数类型
                Type[] actualTypeArguments = type.getActualTypeArguments();
                for (Type t : actualTypeArguments) {
                    System.out.println(t);
                }
                System.out.println("---------------ActualTypeArguments:---------------");
                //获取 返回是类型所属的类型(内部类所属的类型),如果是顶层类型则返回null
                System.out.println("OwnerType=" + type.getOwnerType());
                //获取 有范型的类 的原始类型 比如Map.Entry<T,R> ,是Map
                System.out.println("RawType=" + type.getRawType());
            }
            if (field.getName().equals("animal")) {
                ParameterizedType type = (ParameterizedType) field.getGenericType();
                Type ownerType = type.getOwnerType();
                System.out.println("Person.Animal<String>的ownerType是" + ownerType);
                Type rawType = type.getRawType();
                System.out.println("Person.Animal<String>的rawType是" + rawType);
                Type[] actualTypeArguments = type.getActualTypeArguments();
                for (Type type2 : actualTypeArguments) {
                    //System.out.println("type:" + ((Class)type2).newInstance().getClass());;
                    System.out.println("Person.Animal<String>的actualTypeArguments是" + "获取到的actualTypeArguments分别为:" + type2.getTypeName());
                }
                System.out.println("Person.Animal<String> instanceof ParameterizedType -----" + (type instanceof ParameterizedType));
            }
            System.out.println("--------------" + i + "---------------");
            System.out.println("");
            i++;
        }

    }

public class TypeBean<T> {
     // 1. 是 ParmeterizedType
    public List<String> list;
    
    // 2. 不是 ParmeterizedType
    private Set<String>[] set;
    
    // 3. 不是 ParmeterizedType
    private List noGerList;
    
    // 4. 是 ParmeterizedType
    Map.Entry<String, Integer> entry;
    
    //5. 是 ParmeterizedType
    Person.Animal<String> animal;
    
    //6. 不是 ParmeterizedType
    String str = new String();
    
    //7. 不是 ParmeterizedType
    T t;
    
     //8. 是 ParmeterizedType
    public List<List<String>> doubleList;
    
    //9. 是 ParmeterizedType
    Class<T> classA;
    //10. 是 ParmeterizedType
    Class<?> classB;
}

public class Person {
    @Override
    public String toString() {
        return "Person []";
    }

    class Animal<T> {
        public T name;
    }
}

1.3.2 测试结果

  • 第一个字段List list 是ParameterizedType。
  • 第二个字段Set[] set由于是数组,所以不是ParameterizedType。
  • 第三个字段List noGerList由于没有带泛型,所以也不是ParameterizedType。
  • 第四个字段Map.Entry<String,Integer> entry 是parameterizedType。
  • 第五个字段Person.Animal animal 是parameterizedType。此处我们进一步使用了ParameterizedType的3个方法演示给大家看。我们可以看到ownerType是animal的外部类Person。这也印证了获取到的类型(Person)为原类型(Person.Animal)是其(Person)成员之一。(这里还有其他情况欢迎在评论区告诉。)
    而rawType则是其自身类型。
    getActualTypeArguments()获取到的Type数组则是泛型中的所有类型。(例如Map<k,v>则获取到的数组中包含k,v这两个类型。并且k在前,v在后。)
  • 第六个字段String str = new String();由于没有带泛型所有不是parameterizedType。
  • 第七个字段T t 由于是本类上定义的泛型,所以也不行。
--------------1---------------
field name is : list
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
class java.lang.String
---------------ActualTypeArguments:---------------
OwnerType=null
RawType=interface java.util.List
--------------1---------------

--------------2---------------
field name is : set
field.getGenericType() instanceof ParameterizedType--------false
--------------2---------------

--------------3---------------
field name is : noGerList
field.getGenericType() instanceof ParameterizedType--------false
--------------3---------------

--------------4---------------
field name is : entry
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
class java.lang.String
class java.lang.Integer
---------------ActualTypeArguments:---------------
OwnerType=interface java.util.Map
RawType=interface java.util.Map$Entry
--------------4---------------

--------------5---------------
field name is : animal
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
class java.lang.String
---------------ActualTypeArguments:---------------
OwnerType=class com.noahgroup.supervise.Person
RawType=class com.noahgroup.supervise.Person$Animal

Person.Animal<String>的ownerType是class com.noahgroup.supervise.Person
Person.Animal<String>的rawType是class com.noahgroup.supervise.Person$Animal
Person.Animal<String>的actualTypeArguments是获取到的actualTypeArguments分别为:java.lang.String
Person.Animal<String> instanceof ParameterizedType -----true
--------------5---------------

--------------6---------------
field name is : str
field.getGenericType() instanceof ParameterizedType--------false
--------------6---------------

--------------7---------------
field name is : t
field.getGenericType() instanceof ParameterizedType--------false
--------------7---------------

--------------8---------------
field name is : doubleList
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
java.util.List<java.lang.String>
---------------ActualTypeArguments:---------------
OwnerType=null
RawType=interface java.util.List
--------------8---------------

--------------9---------------
field name is : classA
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
T
---------------ActualTypeArguments:---------------
OwnerType=null
RawType=class java.lang.Class
--------------9---------------

--------------10---------------
field name is : classB
field.getGenericType() instanceof ParameterizedType--------true
---------------ActualTypeArguments:---------------
?
---------------ActualTypeArguments:---------------
OwnerType=null
RawType=class java.lang.Class
--------------10---------------

1.4 TypeVariable的作用

TypeVariable表示的是类型变量,它用来反映在JVM编译该泛型前的信息。例如List中的T就是类型变量,它在编译时需要被转换为一个具体的类型后才能被正常使用。该接口中有三个常用的方法,分别是:

    Type[] getBounds() 获取类型变量的上边界,如果未声明上边界则默认是Object,例如UserService<T extends User>的上边界就是User。

    D getGenericDeclaration() 获取声明该类型的原始类型,例如 UserService<T extends User>的原始类型就是UserService。

    String getName() 获取在源码中定义时的名字,例如UserService<T extends User>中就为T。

1.5 GenericArrayType的作用

GenericArrayType表示的是数组类型且组成元素是ParameterizedType或者是TypeVariable,例如List[] 或 T[]。该接口只有 getGenericComponentType()一个方法,它返回数组的组成元素。

1.6 WildcardType的作用

WildcardType表示的是通配符泛型。WildcardType是依托于ParameterizedType和GenericArrayTypeTest而存在的。

示例如下:
Class<?>
List<? extends Number>
Set<? super T>
    WildcardType接口有两个方法,分别是:

    Type[] getUpperBounds() 返回泛型变量的上界。

    Type[] getLowerBounds() 返回泛型变量的下界。

1.6.1 WildcardType测试

public class WildcardTypeBean<K extends Number & Serializable,V> {
	//1 是 GenericArrayType
	List<? extends Person>[] list;
	//2 是 ParameterizedType
	Set<? super Man> set; 
	//3 是 TypeVariable
	K k;
}


public class WildcardTypeTest {
	public static void main(String[] args) throws Exception{
		Field[] fields = WildcardTypeBean.class.getDeclaredFields();
		for (int i = 0; i <fields.length; i++) {
			System.out.println("--------------"+(i+1));
			Field field = fields[i];
			System.out.println("file:"+field);
			Type type = field.getGenericType();
			if(type instanceof GenericArrayType){
				GenericArrayType gat = (GenericArrayType)type;
				ParameterizedType genericComponentType = (ParameterizedType)gat.getGenericComponentType();
				Type[] actualTypeArguments = genericComponentType.getActualTypeArguments();
				WildcardType t = (WildcardType)actualTypeArguments[0];
				Type[] upperBounds = t.getUpperBounds();
				for (Type type2 : upperBounds) {
					System.out.println("upperBounds:"+type2.getTypeName());
				}
				Type[] lowerBounds = t.getLowerBounds();
				for (Type type2 : lowerBounds) {
					System.out.println("lowerBounds:"+type2.getTypeName());
				}
			}else if(type instanceof ParameterizedType){
				WildcardType wildcardType = ((WildcardType)((ParameterizedType) type).getActualTypeArguments()[0]);
				Type[] lowerBounds = wildcardType.getLowerBounds();
				for (Type type2 : lowerBounds) {
					System.out.println("lowerBounds:"+type2.getTypeName());
				}
			}else{
				System.out.println(type.getTypeName()+" instanceof "+type.getClass());
			}
			System.out.println("--------------"+(i+1));
		}
}

1.6.2 测试结果

--------------1
file:java.util.List[] WildcardTypeBean.list
upperBounds:Person
--------------1

--------------2
file:java.util.Set WildcardTypeBean.set
lowerBounds:Man
--------------2

--------------3
file:java.lang.Number WildcardTypeBean.k
K instanceof class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
--------------3

文章参考

  1. Type类型详解
  2. Type接口的基础知识
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值