前言
Java 编程语言从Java 5以后就引入Type体系,大大方便了我们代码的编写和优化,但是当泛型擦除时,擦除类型变量,并替换为限定类型,此时我们在运行时期便无法获取泛型类原本所带的泛型。所以java引入了Type这一概念。Type也主要是为在运行时期获取泛型而服务。
一、Type是什么?
Type是一个空接口,所有类型的公共接口,其意义表示Java所有类型,这里的类型是从Java整个语言角度来看的,比如原始类型、参数化类型(泛型)、类型变量及其泛型数组等,可以理解为,Class是Java对现实对象的抽象,而Type是对Java语言对象的抽象。
二、Type接口
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
实现了Type接口的子接口为GenericArrayType(泛型数组类型),ParmeterizedType(参数化类型),TypeVariable(类型变量),WildcardType(通配符类型)。实现了Type接口的子类有Class(类)。所以Type一共可以表示这5类数据。主要介绍的就是四个子接口。
二、ParameterizedType(参数化类型)
parameterizedType主要是用来表示带参数的类型,如 Collection、HashMap<String,Integer>等。parameterizedType表示的类型非常的简单,只要带着泛型,除了不可以是数组和本类上定义的泛型以外,其他都被列入ParameterizedType的范围。
package java.lang.reflect;
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();
}
三、TypeVariable
类型变量,例如List中的T, Map<K,V>中的K和V
interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
//返回此类型参数的上界列表,如果没有上界则放回Object. 例如 V extends Person 这个类型参数,有1个上界Person
Type[] getBounds();
//类型参数声明时的载体,例如 `class HashMap<K, V >` ,那么V 的载体就是HashMap
D getGenericDeclaration();
String getName();
//返回一个AnnotatedType对象的数组,表示使用类型来表示此TypeVariable表示的类型参数的上限。
//即如果这个这个泛型参数类型的上界用注解标记了,我们可以通过它拿到相应的注解。
AnnotatedType[] getAnnotatedBounds();
}
从typeVariable的定义看到它也有一个泛型参数,要求需要是GenericDeclaration 的子类。interface TypeVariable < D extends GenericDeclaration >.
//所有可以申明泛型参数的entities都必须实现这个接口
public interface GenericDeclaration extends AnnotatedElement {
public TypeVariable<?>[] getTypeParameters();
}
而三个类实现了这个接口,分别是:
java.lang.reflect.Method,
java.lang.reflect.Constructor,
java.lang.Class
所以我们只能在类型(Class,Interface)、方法和构造函数这三个地方声明泛型参数,其他地方不能使用。
四、GenericArrayType
泛型数组类型,用来作为数组的泛型声明类型。例如List[] ltArray, T[] tArray两个数组,其中List[], 和T[]就是GenericArrayType`类型。
public interface GenericArrayType extends Type {
//获取泛型类型数组的声明类型,即获取数组方括号 [] 前面的部分
Type getGenericComponentType();
}
GenericArrayType 接口只有一个方法 getGenericComponentType(),其可以用来获取数组方括号 [] 前面的部分,例如T[],在其上调用getGenericComponentType 就可以获得T. 值得注意的是多维数组得到的是最后一个[] 前面的部分,例如T[][], 得到的是T[].
五、WildcardType
通配符类型,即带有?的泛型参数, 例如 List<?>中的?,List<? extends Number>里的? extends Number 和List<? super Integer>的? super Integer 。
public interface WildcardType extends Type {
// 获取上界
Type[] getUpperBounds();
//获取下界
Type[] getLowerBounds();
}
总结
Type类型平时很少遇到,但是翻阅JDK的源码时,有时候就会遇到,对于Type类型有所了解,能够加快我们对于代码的理解。亦如在JDK8之HashMap的comparableClassFor方法。