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>。