Java Type接口 & 运行时获取泛型类型

一、Type接口

Type是所有类型的父接口,他有4个子接口和一个实现类。
这里写图片描述

  1. Class比较常见,它表示的是原始类型。Class类的对象表示JVM中的一个类或接口。每个Java类在JVM里都表现为一个Class对象,可以通过“类名.class”、“对象.getClass()”、“Class.forName(“类名”)”等方式获取Class对象。数组也被映射为Class对象,所有元素类型相同且维数相同的数组都共享同一个Class对象。
  2. ParameterizedType表示的是参数化类型,例如List<String>、Map<Integer,String>、Service<User>这种带有泛型的类型。
    ParameterizedType接口中常用的方法有3个,分别是:
    (1) Type getRawType()——返回参数化类型中的原始类型,例如List<String>的原始类型为List。
    (2) Type[] getActualTypeArguments()——获取参数化类型的类型变量或是实际类型列表,例如Map<Integer,String>的实际泛型列表是Integer和String。需要注意的是,该列表的元素类型是Type,也就是说,可能存在多重嵌套的情况。
    (3) Type getOwerType()——返回的是类型所属的类型,例如存在A<T>,其中定义了内部类InnerA<T>,则InnerA<T>所属的类型是A<T>,如果是顶层类型则返回null。这种关系常见与Map<K,V>接口与Map.Entry<K,V>接口,Map<K,V>是Map.Entry<K,V>接口的所有者。
  3. TypeVariable表示的是类型变量,它用来反映的是JVM编译该泛型前的信息,例如List<T>中的T就是类型变量,它在编译时需要被转换为一个具体的类型后才能正常使用。
    该接口常用的方法有3个,分别是:
    (1) Type[] getBounds()——获取类型变量的上边界,如果未明确声明上边界则默认为Object。例如Class<K extents Person>中K的上边界就是Person。
    (2) D getGenericDeclaration()——获取声明该类型变量的原始类型,例如Test<K extents Person>中原始类型是Test。
    (3) String getName()——获取在源码中定义的名字,上例中为K。
  4. GenericArrayType表示的是数组类型且组成元素时ParameterizedType或TypeVariable,例如List<T>或T[],该接口只有Type getGenericComponentType()一个方法,它返回数组的组成元素类型。
  5. WildcardType表示的通配符类型,例如? extends Number 和 ? super Integer。
    Wildcard接口有两个方法,分别是:
    (1) Type[] getUpperBounds()——返回类型变量的上边界。
    (2) Type[] getLowerBounds()——返回类型变量的下边界。

二、ParameterizedType与TypeVariable的使用

1.未指定泛型参数的泛型类(例如:ArrayList<T>)

public class TypeTest {
    public static void main(String[] args) {
        System.out.println("接口是否是泛型类:"+ (ArrayList.class.getGenericInterfaces()[0] instanceof ParameterizedType));
        System.out.println("泛型类的名称:"+ ArrayList.class.getGenericInterfaces()[0].getTypeName());
        System.out.println("泛型类的实现:"+ ArrayList.class.getGenericInterfaces()[0].getClass());
        System.out.println("是否是泛型参数:"+(((ParameterizedType)ArrayList.class.getGenericInterfaces()[0]).getActualTypeArguments()[0] instanceof TypeVariable));
        System.out.println("泛型参数名称:"+((ParameterizedType)ArrayList.class.getGenericInterfaces()[0]).getActualTypeArguments()[0].getTypeName());
        System.out.println("泛型参数的实现:"+((ParameterizedType)ArrayList.class.getGenericInterfaces()[0]).getActualTypeArguments()[0].getClass());
    }
}

//输出结果:
接口是否是泛型类:true
泛型类的名称:java.util.List<E>
泛型类的实现:class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
是否是泛型参数:true
泛型参数名称:E
泛型参数的实现:class sun.reflect.generics.reflectiveObjects.TypeVariableImpl

  在这里,我们使用的是ArrayList.class,如果使用new ArrayList<String>().getClass(),是否得到的泛型参数就是String呢?答案是否定的,因为this.getClass() 对象是被所有的不同具体类型的ArrayList实例 共享的(例如:new ArrayList<String>(), new ArrayList<Integer>() 等),所以在字节码中类型会被擦除到上限。

2.指定泛型参数的泛型类(例如:GenericSubClass<String>)

public class GenericClass<T> {
}

public class GenericSubClass1<String> extends GenericClass<String> {
}

public class GenericSubClass2 extends GenericClass<String> {
}

public class TypeTest {
    public static void main(String[] args) {
        Class clazz = GenericSubClass1.class;
        //Class clazz = GenericSubClass2 .class;
        //Class clazz = new GenericSubClass1().getClass();
        //Class clazz = new GenericSubClass2().getClass();
        System.out.println("父类是否是泛型类:"+ (clazz.getGenericSuperclass() instanceof ParameterizedType));
        System.out.println("泛型类的名称:"+ clazz.getGenericSuperclass().getTypeName());
        System.out.println("泛型类的实现:"+ clazz.getGenericSuperclass().getClass());
        System.out.println("是否是泛型参数:"+(((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0] instanceof TypeVariable));
        System.out.println("泛型参数名称:"+((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0].getTypeName());
        System.out.println("泛型参数的实现:"+((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0].getClass());
    }
}

//输出结果:
父类是否是泛型类:true
泛型类的名称:com.arch.test.reflect.GenericClass<String>
泛型类的实现:class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
是否是泛型参数:true
泛型参数名称:String
泛型参数的实现:class sun.reflect.generics.reflectiveObjects.TypeVariableImpl

  不管是使用"类.class",还是使用"对象.getClass()",得到的父类的泛型参数始终是String。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值