Java类型-Type系统

Type是Java中所有类型的公共高级接口,也就是Java中所有类型的"爹"。

public interface Type {
    //返回这个类型的描述,包括此类型的参数描述.
    default String getTypeName() {
        return toString();
    }
}

Type体系中类型包括:
原始类型,基本类型(Class),参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、通配符类型(WildcardType);

在这里插入图片描述


示例类TypeTest是一个泛型类,声明了两个泛型参数T和V,一个构造函数和一个泛型方法以及若干属性。
在这里插入图片描述


自定义注解Custom:
在这里插入图片描述
下面的code都是以上面的类为基础写的.
个人觉得我们应该先从TypeVariable作为切入点来进入Java Type的世界, 因为它是其他类型的基础.

1. TypeVariable:

类型变量,例如List<T>中的T, Map<K,V>中的K和V, 我们的测试类class TypeTest<T, V extends @Custom Numer & Serializable>中的T和V.
此接口的源码如下:
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     *返回此类型参数的上界列表,如果没有上界则返回Object,
     例如 V extends @Custom Number & Serializable 这个类型参数,
     有两个上界,Number 和Serializable
    */
    Type[] getBounds();

	//类型参数声明时的载体,例如
	//class Typetest<T, V extends @Custom Number & Serialzable>
	//那么V 的载体就是TypeTest
	D getGenericDeclaration();

	String getName();
    /**
     * Java 1.8加入AnnotatedType:如果这个泛型参数类型的上界用注解标记了,我们可以通过它拿到相应的注解
     */
     AnnotatedType[] getAnnotatedBounds();
}

从typeVariable的定义看到其也有一个泛型参数,要求需要是GenericDeclaration的子类,

//所有可以声明泛型参数的Entities都必须实现这个接口
public interface GenericDeclaration extends AnnotatedElement {
	public TypeVariable<?>[] getTypeParameters();
}

在这里插入图片描述
输出结果为:

TypeVariable1:V
TypeVariable2:[class java.lang.Number, interface java.io.Serializable]
TypeVariable3:class com.xianyiquan.gmall.impl.TypeTest
TypeVariable4:[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@4dd8dc3, sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@6d03e736] : [@com.xianyiquan.gmall.impl.Custom()]
TypeVariable5:V

2. ParameterizedType:

参数化类型,即泛型,例如:List<T>、Map<K,V>等带有参数化的对象;
public interface ParameterizedType extends Type {
    //获取 参数类型<>里面的那些值,例如Map<K,V>那么就得到[K,V]的一个数组
    Type[] getActualTypeArguments();

    //获得参数类型<>前面的值,例如Map<K,V>那么就得到Map
    Type getRawType();

    //获取其父类的类型,例如Map有一个内部类Entry,那么在Map.Entry<K,V>上调用这个方法就可以获得Map
    Type getOwnerType();
}

实际操作
在这里插入图片描述
输出
在这里插入图片描述
上面的代码,先使用反射获取TypeTest类的List list 和Map <String, T> map属性的类型,然后调用getGenericType()获取他们的声明类型,他们是ParameterizedType类型,然后调用里面的方法.


3. GennericArrayType

泛型数组类型,用来作为数组的泛型声明类型,例如List [] ltArray, T[] tArray两个数组,其中List[] ,和 T[]就是GenericArrayType类型.
源码:

public interface GenericArrayType extends Type {
    //获取泛型类型数组的声明类型,即获取数组方括号 [] 前面的部分
    Type getGenericComponentType();
}

GenericArrayType接口只有一个方法getGenericComponentType(),其可以用来获取数组方括号 [] 前面的部分,例如 T[] ,在其上调用getGenericComponentType就可以获得T
值得注意的是多维数组得到的是最后一个[ ]前面的部分,例如 T[ ] [ ],得到的是T[ ]。
上code:
在这里插入图片描述
在这里插入图片描述

上界 <? extend Fruit>表示所有继承Fruit的子类,但是具体是哪个子类,无法确定,所以调用add的时候,要add什么类型,谁也不知道。但是get的时候,不管是什么子类,不管追溯多少辈,肯定有个父类是Fruit,所以,我都可以用最大的父类Fruit接着,也就是把所有的子类向上转型为Fruit。

下界 <? super Apple>表示Apple的所有父类,包括Fruit,一直可以追溯到老祖宗Object 。那么当我add的时候,我不能add Apple的父类,因为不能确定List里面存放的到底是哪个父类。但是我可以add Apple及其子类。因为不管我的子类是什么类型,它都可以向上转型为Apple及其所有的父类甚至转型为Object 。但是当我get的时候,Apple的父类这么多,我用什么接着呢,除了Object,其他的都接不住。
归根结底可以用一句话表示,那就是编译器可以支持向上转型,但不支持向下转型

4. WildcardType:

通配符类型,即带有?的泛型参数, 例如 List<?>中的?,List<? extends Number>里的? extends Number 和List<? super Integer>的? super Integer 。
此接口源码如下:

public interface WildcardType extends Type {
   // 获取上界
	Type[] getUpperBounds();
	//获取下界
	Type[] getLowerBounds();
}

code:

 Field mapWithWildcard = TypeTest.class.getField("mapWithWildcard");
 Type wild = mapWithWildcard.getGenericType();//先获取属性的泛型类型 Map<? super String, ? extends Number>
 if (wild instanceof ParameterizedType) {
     ParameterizedType pType = (ParameterizedType) wild;
     Type[] actualTypes = pType.getActualTypeArguments();//获取<>里面的参数变量 ? super String, ? extends Number
     System.out.println("WildcardType1:" + Arrays.asList(actualTypes));
     WildcardType first = (WildcardType) actualTypes[0];//? super java.lang.String
     WildcardType second = (WildcardType) actualTypes[1];//? extends java.lang.Number
     System.out.println("WildcardType2: lower:" + Arrays.asList(first.getLowerBounds()) + "  upper:" + Arrays.asList(first.getUpperBounds()));//WildcardType2: lower:[class java.lang.String]  upper:[class java.lang.Object]
     System.out.println("WildcardType3: lower:" + Arrays.asList(second.getLowerBounds()) + "  upper:" + Arrays.asList(second.getUpperBounds()));//WildcardType3: lower:[]  upper:[class java.lang.Number]
 }

输出:

WildcardType1:[? super java.lang.String, ? extends java.lang.Number]
WildcardType2: lower:[class java.lang.String]  upper:[class java.lang.Object]
WildcardType3: lower:[]  upper:[class java.lang.Number]

5. Class

其是Type的一个实现类,是反射的基础,每一个类在虚拟机中都对应一个Calss 对象,我们可以用在运行时从这个Class对象中获取到类型所有信息。

 Field tClass = TypeTest.class.getField("testClass");
 //获取泛型类型,由于我们这个属性声明时候没有使用泛型,所以会获得原始类型
 System.out.println("Class1:" + tClass.getGenericType());
 Field tClass2 = TypeTest.class.getField("testClass2");
 //获取泛型类型
 System.out.println("Class2:" + tClass2.getGenericType());

输出:

Class1:class typeInfo.TypeTest
Class2:typeInfo.TypeTest<T, java.lang.Integer>

可以看到 属性 public TypeTest testClass; 通过getGenericType()获取到的类型就是其原始类型TypeTest。而属性 public TypeTest<T, Integer> testClass2;获取到的则是ParameterizedType类型TypeTest<T, java.lang.Integer>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值