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。

java class和type关系 java里的class和type_java

/***
 * 泛型参数可以在三种 位置声明: 类或则接口、 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