Type和泛型的关系
Java 5以后加入了泛型特性,关于泛型的类型是什么?就要用到Type 类来描述。
package java.lang.reflect;
public interface Type {
default String getTypeName() {
return this.toString();
}
}
Type 接口有一个我们熟悉的实现类 Class 类, 还有四个接口类型TypeVariable、ParameterizedType、WildcardType、GenericArrayType。
从泛型参数的声明开始
这里的泛型参数指的是 里的 T,可以在三种 位置声明: 类或者接口、 Method、 构造方法 。具体是由GenericDeclaration 这个接口决定的,顾名思义这个接口就是指哪些类上可以声明泛型。
public interface GenericDeclaration extends AnnotatedElement {
public TypeVariable<?>[] getTypeParameters();
}
GenericDeclaration 它的实现类有 Method 、Constructor、Class。
/***
* 泛型参数可以在三种 位置声明: 类或则接口、 Method、 构造方法
* @param <T>
*/
public class GenericDemo<T extends Number> {
private CharSequence name;
// Class 上声明的 泛型参数 T 。
public T t; //t是 TypeVariable 类型
public HashMap<CharSequence, T> hashMap = new HashMap<>(); // hashMap 是 ParameterizedType 类型
public HashMap rawHashMap = new HashMap<>(); // rawHashMap 是 原生类型,所以是 class 类型。
public T[] tArray; // tArray 是 GenericArrayType 类型
public HashMap<? extends CharSequence, T> wildHashMap = new HashMap<>(); // wildHashMap 是 ParameterizedType 类型。 它的第一个参数 ? extends CharSequence 是 WildcardType 。
// 构造方法处声明的泛型参数 E
public <E extends CharSequence> GenericDemo(E e) {
name = e;
}
// 非静态方法上声明的 泛型参数 K
public <K extends T> void setT(K k) {
t = k;
}
// 静态方法上声明的泛型参数 K ,和上面非静态方法的 K 不是同一种类型,不冲突
public static <K> void staticMethod(K k) {
System.out.println(" test " + k.getClass());
}
}
从TypeVariable 开始
参数变量,泛型的开始都是从参数的声明开始,例如 Map<K,V>中的K和V。这个 K 和V 就是TypeVariable
interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
//返回泛型参数的上界列表, 泛型的声明只有 extends 形式。
Type[] getBounds();
//泛型参数是在哪里形式声明的,Method 、Constructor、Class
D getGenericDeclaration();
String getName();
}
测试代码:
public static void main(String args[]){
try{
// public T t;
Field field = GenericDemo.class.getField("t");
TypeVariable typeVariable = (TypeVariable) field.getGenericType();
System.out.println("typeVariable toString " + typeVariable);
System.out.println("typeVariable 的泛型边界" + Arrays.asList(typeVariable.getBounds()));
System.out.println("TypeVariable 的声明位置" + typeVariable.getGenericDeclaration());
}catch (Exception e){
}
}
输出 :
typeVariable toString T
typeVariable 的泛型边界[class java.lang.Number]
TypeVariable 的声明位置class com.example.diva.leet.GenericDemo
ParameterizedType
参数化类型。上面的TypeVariable 完全就是变量如:T 而不是一种确切的类型。这个ParameterizedType我们就比较熟悉了。它是带有具体class 信息 的。如 List< T > 、List< String > 。
public interface ParameterizedType extends Type {
// 获取 < > 内的 参数信息 。如HashMap< String, T> 中的 String 和 T 。
// String 是 class 类型 ,T 是TypeVariable 类型
Type[] getActualTypeArguments();
// 获取原生类型 ,如 List<T> 的 List 类型它属于 Class 类型。
Type getRawType();
// 获取外部类的类型,如果没有外部类,返回Null
Type getOwnerType();
}
测试代码:
public static void main(String args[]){
try{
// public HashMap<CharSequence, T> hashMap = new HashMap<>();
Field field = GenericDemo.class.getField("hashMap");
ParameterizedType parameterizedType = (ParameterizedType)field.getGenericType();
System.out.println("parameterizedType toString " + parameterizedType);
System.out.println("parameterizedType 的参数信息 " + Arrays.asList(parameterizedType.getActualTypeArguments()));
System.out.println("parameterizedType 的原生类型 " + parameterizedType.getRawType());
System.out.println("hashMap<CharSequence,T> 的第二个参数类型 " + parameterizedType.getActualTypeArguments()[1].getClass());
}catch (Exception e){
}
}
输出:
parameterizedType toString java.util.HashMap<java.lang.CharSequence, T>
parameterizedType 的参数信息 [interface java.lang.CharSequence, T]
parameterizedType 的原生类型 class java.util.HashMap
hashMap 的第二个参数类型 class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
WildcardType
带通配符的类型 。也就是 HashMap<? extends CharSequence, T> 的第一个泛型参数 ? extends CharSequence 。
它的作用和 TypeVariable 一样,是用来描述参数信息的, 和原生类型无关。
public interface WildcardType extends Type {
// 获取 extends 的类型
Type[] getUpperBounds();
//获取 super 的类型
Type[] getLowerBounds();
}
测试代码:
public static void main(String args[]) {
try {
// public HashMap<? extends CharSequence, T> wildHashMap = new HashMap<>();
Field field = GenericDemo.class.getField("wildHashMap");
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
WildcardType wildcardType = (WildcardType) parameterizedType.getActualTypeArguments()[0];
System.out.println("wildcardType toString " + wildcardType);
System.out.println("wildcardType 的上界是 " + Arrays.asList(wildcardType.getUpperBounds()));
System.out.println("wildcardType 的下界是 " + Arrays.asList(wildcardType.getLowerBounds()));
} catch (Exception e) {
}
}
输出 :
wildcardType toString ? extends java.lang.CharSequence
wildcardType 的上界是 [interface java.lang.CharSequence]
wildcardType 的下界是 []
GenericArrayType
泛型数组类型。
public interface GenericArrayType extends Type {
// 获取数组的类型
Type getGenericComponentType();
}
测试代码:
public static void main(String args[]) {
try {
Field field = GenericDemo.class.getField("tArray");
Type type = field.getGenericType();
System.out.println("T[] 的类型是 " +type.getClass());
System.out.println(" T[] getGenericComponentType() 的类型是 " + ((GenericArrayType) type).getGenericComponentType().getClass());
} catch (Exception e) {
}
}
输出:
T[] 的类型是 class sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
T[] getGenericComponentType() 的类型是 class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
Class
Class 类型代表的也就是 Raw 类型,它不含泛型信息。
测试代码:
public static void main(String args[]) {
try {
// 以 HashMap rawHashMap 和 HashMap<CharSequence, T> hashMap 为对比
Field rawHashMap = GenericDemo.class.getField("rawHashMap");
Field hashMap = GenericDemo.class.getField("hashMap");
System.out.println(" HashMap rawHashMap 的类型是 "+rawHashMap.getGenericType().getClass());
System.out.println(" HashMap<CharSequence, T> hashMap 的类型是 " +hashMap.getGenericType().getClass());
} catch (Exception e) {
}
}
输出:
HashMap rawHashMap 的类型是 class java.lang.Class
HashMap<CharSequence, T> hashMap 的类型是 class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl