没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型(ParameterizedType)、类型变量(TypeVariable) 、泛型数组类型(GenericArrayType),通配符类型(WildcardType)。
深入了解Java对类型的管理,对我们理解序列化、反序列化的深入理解讲非常有帮助。类型的父类为Type,它位于反射包java.lang.reflect内。


Type包括:GenericArrayType(范型数组类型,图中没有)、ParameterizedType(参数化类型)、WildcardType( 泛型表达式类型/通配符类型)、TypeVariable(类型变量)、Class(原始/基本类型)。

Class(原始/基本类型,也叫raw type):不仅仅包含我们平常所指的类、枚举、数组(String[]、byte[])、注解,还包括基本类型(原始类型(primitive type 虚拟机创建 8种int 、float加void)对应的包装引用类型Integer、Float等等

ParameterizedType(参数化类型):就是我们平常所用到的带< >符号的泛型,如List< Student >、Map<String,String>(注意和TypeVariable的区别),ParameterizedType的getRawType是List,Map; getActualTypeArguments是Student和 String String;getOwnerType是找内部类定义在哪个类中。

TypeVariable(类型变量):比如List< T >中的T,U,V等。TypeVariable有getBounds()界限数组和getGenericDeclaration()定义在哪个类中的方法。而List< T >是ParameterizedType,ParameterizedType的getRawType是List; getActualTypeArguments是T,T是TypeVariable,

WildcardType( 通配符类型):例如List< ? extends Number>中的? extends Number,WildcardType有上下界方法。而List< ? extends Number>本身是ParameterizedType,ParameterizedType的getRawType()方法获取到的是List; getActualTypeArguments是? extends Number,? extends Number是WildcardType。

GenericArrayType(带有范型数组类型):并不是我们工作中所使用的数组String[]、byte[](这种都属于Class),而是带有泛型的数组即含有< >或者T U等的数组,即T[] 或者List< String >[],GenericArrayType的genericComponentType()方法获取到的是TypeVariable T或者ParameterizedType List< String >。
Spring提供了更具统一的类型抽象:ResolvableType(可辨别的类型),内部有Type成员变量

Type的直接子类只有一个,也就是Class,代表着类型中的原始类型(PrimitiveType

These include* {@code boolean}, {@code byte}, {@code short}, {@code int},* {@code long}, {@code char}, {@code float}, and {@code double}.

)以及基本类型。

public interface Type {default String getTypeName() {return toString();}
}

1.GenericArrayType(数组类型)
泛型数组,描述的是形如:Person[]或T[]类型变量Person和原始类型T

public interface GenericArrayType extends Type {//返回泛型数组中元素的component组成部分的Type类型,// 即List<String>[] 中的 List<String>Type getGenericComponentType();
}

看如下代码,会对各种Type类型有一个直观的认识:

package com.example.test;import java.lang.reflect.*;
import java.util.List;public class GeneticTypeTest<T> {// 这里面有各种各样的数组:各有不同 方便看测试效果// 含有泛型数组的才是GenericArrayTypepublic void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray, List<String> list, List<T> typeVariableList,List<? extends Number> wildcardList, String[] strings, GeneticTypeTest[] test) {}public static void main(String[] args) {Method[] declaredMethods = GeneticTypeTest.class.getDeclaredMethods();for (Method method : declaredMethods) {// main方法不用处理if (method.getName().startsWith("main")) {continue;}// 开始处理该方法===打印出此方法签名System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])// 该方法能获取到该方法所有的实际的参数化类型,比如本例中有五个参数,那数组长度就是5Type[] types = method.getGenericParameterTypes();// 分组打印出来for (Type type : types) {if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;System.out.println("**************");System.out.println("ParameterizedType type [list typeVariableList wildcardList]: " + parameterizedType);System.out.println("ParameterizedType's rawType: " + parameterizedType.getRawType());System.out.println("ParameterizedType's ownerType is " + (parameterizedType.getOwnerType()));System.out.println("ParameterizedType's actualType is  " + parameterizedType.getActualTypeArguments()[0]);System.out.println("ParameterizedType's actualType is TypeVariable " + (parameterizedType.getActualTypeArguments()[0] instanceof TypeVariable));System.out.println("ParameterizedType's actualType is WildcardType " + (parameterizedType.getActualTypeArguments()[0] instanceof WildcardType));System.out.println("ParameterizedType's actualType is Class " + (parameterizedType.getActualTypeArguments()[0] instanceof Class));System.out.println("**************");}if (type instanceof GenericArrayType) {System.out.println("---------------");GenericArrayType genericArrayType = (GenericArrayType) type;System.out.println("GenericArrayType type [pTypeArray vTypeArray]: " + genericArrayType);Type genericComponentType = genericArrayType.getGenericComponentType();System.out.println("genericComponentType [pTypeArray vTypeArray's component Type]:" + genericComponentType);System.out.println("---------------");}if (type instanceof WildcardType) {WildcardType wildcardType = (WildcardType) type;System.out.println("WildcardType type [wildcardList]: " + wildcardType);}if (type instanceof TypeVariable) {TypeVariable typeVariable = (TypeVariable) type;System.out.println("TypeVariable type [typeVariable]:" + typeVariable);}if (type instanceof Class) {Class clazz = (Class) type;System.out.println("type [strings test]: " + clazz);}}}}
}

输出结果:

declare Method:public void com.example.test.GeneticTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.util.List,java.util.List,java.lang.String[],com.example.test.GeneticTypeTest[])
---------------
GenericArrayType type [pTypeArray vTypeArray]: java.util.List<java.lang.String>[]
genericComponentType [pTypeArray vTypeArray's component Type]:java.util.List<java.lang.String>
---------------
---------------
GenericArrayType type [pTypeArray vTypeArray]: T[]
genericComponentType [pTypeArray vTypeArray's component Type]:T
---------------
**************
ParameterizedType type [list typeVariableList wildcardList]: java.util.List<java.lang.String>
ParameterizedType's rawType: interface java.util.List
ParameterizedType's ownerType is null
ParameterizedType's actualType is  class java.lang.String
ParameterizedType's actualType is TypeVariable false
ParameterizedType's actualType is WildcardType false
ParameterizedType's actualType is Class true
**************
**************
ParameterizedType type [list typeVariableList wildcardList]: java.util.List<T>
ParameterizedType's rawType: interface java.util.List
ParameterizedType's ownerType is null
ParameterizedType's actualType is  T
ParameterizedType's actualType is TypeVariable true
ParameterizedType's actualType is WildcardType false
ParameterizedType's actualType is Class false
**************
**************
ParameterizedType type [list typeVariableList wildcardList]: java.util.List<? extends java.lang.Number>
ParameterizedType's rawType: interface java.util.List
ParameterizedType's ownerType is null
ParameterizedType's actualType is  ? extends java.lang.Number
ParameterizedType's actualType is TypeVariable false
ParameterizedType's actualType is WildcardType true
ParameterizedType's actualType is Class false
**************
type [strings test]: class [Ljava.lang.String;
type [strings test]: class [Lcom.example.test.GeneticTypeTest;

上述例子中属于GenericArrayType:List[] pTypeArray, T[] vTypeArray它哥俩都是泛型数组。但是这两String[] strings,GeneticTypeTest[] test 属于Class普通类型,因为不含范型。
GenericArrayType的getGenericComponentType()返回的类型为Type(ParameterizedTypeImpl)类型,能够获取到数组的实际参数(组成)类型
2.ParameterizedType(参数化类型)
参数化类型,即泛型;例如:List< T>、Map< K,V>,Person、LIst等带有参数化的对象。

public interface ParameterizedType extends Type {//获取类型内部的参数化类型 比如Map<K,V>里面的K,V类型,List<T>中的T ,List<? extends Number>中的? extends java.lang.Number,例如Person<Student>中的Student,List<String>中的StringType[] getActualTypeArguments();// 类的原始类型,一般都是Class,例如Person<Student>中的Person,List<String>中的interface List,List<? extends Number>中的中的ListType getRawType();// 针对内部类:获取所有者类型// (只有内部类才有所有者,比如Map.Entry他的所有者就是Map),// 若不是内部类,此处返回nullType getOwnerType();
}

再看一个例子,说明ParameterizedType

package com.example.test;import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;public class ParameterizedTypeTest {private Map<String, ParameterizedTypeTest> map;private Set<String> set1;private Class<?> clz;private Holder<String> holder;private List<String> list;private ArrayList<String> arrayList;private Map.Entry<String, String> entry;private String str;private Integer i;private Set set;private List aList;static class Holder<V> {}public static void main(String[] args) {Field f = null;try {// 拿到所有的字段Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();for (int i = 0; i < fields.length; i++) {f = fields[i];if (f.getGenericType() instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();System.out.println(f.getName() + ":");System.out.println("\t ParameterizedType actual type:" + Arrays.asList(parameterizedType.getActualTypeArguments()));System.out.println("\t getRawType:" + parameterizedType.getRawType());System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType());}// 输出不是ParameterizedType 参数化类型的else {System.out.println(f.getName() + ":is not ParameterizedType ");}}} catch (Exception e) {}}
}

输出结果:

map:ParameterizedType actual type:[class java.lang.String, class com.example.test.ParameterizedTypeTest]getRawType:interface java.util.MapgetOwnerType:null
set1:ParameterizedType actual type:[class java.lang.String]getRawType:interface java.util.SetgetOwnerType:null
clz:ParameterizedType actual type:[?]getRawType:class java.lang.ClassgetOwnerType:null
holder:ParameterizedType actual type:[class java.lang.String]getRawType:class com.example.test.ParameterizedTypeTest$HoldergetOwnerType:class com.example.test.ParameterizedTypeTest
list:ParameterizedType actual type:[class java.lang.String]getRawType:interface java.util.ListgetOwnerType:null
arrayList:ParameterizedType actual type:[class java.lang.String]getRawType:class java.util.ArrayListgetOwnerType:null
entry:ParameterizedType actual type:[class java.lang.String, class java.lang.String]getRawType:interface java.util.Map$EntrygetOwnerType:interface java.util.Map
str:is not ParameterizedType
i:is not ParameterizedType
set:is not ParameterizedType
aList:is not ParameterizedType

先看最后几个is not…的类型,发现即使是List,但是我们没给与泛型,它不会是ParameterizedType参数化类型。然后holder和entry的getOwnerType不是null,因为他俩类型都是内部类,所以有所有者类型。其它的owner类都是null。getRawType其实就是返回了本类的本来的Class类型。getActualTypeArguments:获取到泛型类型,返回一个数组(因为可能会有多个)

3.WildcardType( 通配符,泛型表达式类型)
通配符表达式,或泛型表达式,它虽然是Type的一个子接口,但并不是Java类型中的一种,表示的仅仅是类似 ? extends T、? super K这样的通配符表达式。?—通配符表达式,表示通配符泛型
WildcardType接口的定义

public interface WildcardType extends Type {//获得泛型表达式上界(上限) 获取泛型变量的上边界(extends) Type[] getUpperBounds();//获得泛型表达式下界(下限) 获取泛型变量的下边界(super)Type[] getLowerBounds();
}

看下边代码:

package com.example.test;import java.lang.reflect.*;
import java.util.List;
import java.util.Map;public class WildcardTypeTest {private List<? extends Number> listUpper;private List<? super String> listLower;private List<String> list;private Map<? extends String, ? super Number> map1;private Map<? extends String, ?> map2;private Class<?> clazz;// 不写泛型的listprivate List objList;private static void printWildcardType(WildcardType wildcardType) {for (Type type : wildcardType.getUpperBounds()) {System.out.println("\t\t上界:" + type);}for (Type type : wildcardType.getLowerBounds()) {System.out.println("\t\t下界:" + type);}}public static void main(String[] args) {Field f = null;try {Field[] fields = WildcardTypeTest.class.getDeclaredFields();for (int i = 0; i < fields.length; i++) {f = fields[i];System.out.println("begin ******当前field:" + f.getName() + " *************************");Type genericType = f.getGenericType(); // 获取字段的泛型参数if (genericType instanceof ParameterizedType) {System.out.println("\tParameterizedType type :" + genericType);ParameterizedType parameterizedType = (ParameterizedType) genericType;for (Type type : parameterizedType.getActualTypeArguments()) {//参数化类型可能有多个System.out.println("\t  获取到getActualTypeArguments为:" + type);if (type instanceof WildcardType) {printWildcardType((WildcardType) type);}}} else if (genericType instanceof GenericArrayType) {GenericArrayType genericArrayType = (GenericArrayType) genericType;System.out.println("\tGenericArrayType type :" + genericArrayType);Type genericComponentType = genericArrayType.getGenericComponentType();if (genericComponentType instanceof WildcardType) {printWildcardType((WildcardType) genericComponentType);}} else if (genericType instanceof TypeVariable) {TypeVariable typeVariable = (TypeVariable) genericType;System.out.println("\ttypeVariable:" + typeVariable);} else if(genericType instanceof Class) {System.out.println("\ttype :" + genericType);if (genericType instanceof WildcardType) {printWildcardType((WildcardType) genericType);}}System.out.println("end ******当前field:" + f.getName() + " *************************");System.out.println();}} catch (Exception e) {}}
}

输出结果:

begin ******当前field:listUpper *************************ParameterizedType type :java.util.List<? extends java.lang.Number>获取到getActualTypeArguments为:? extends java.lang.Number上界:class java.lang.Number
end ******当前field:listUpper *************************begin ******当前field:listLower *************************ParameterizedType type :java.util.List<? super java.lang.String>获取到getActualTypeArguments为:? super java.lang.String上界:class java.lang.Object下界:class java.lang.String
end ******当前field:listLower *************************begin ******当前field:list *************************ParameterizedType type :java.util.List<java.lang.String>获取到getActualTypeArguments为:class java.lang.String
end ******当前field:list *************************begin ******当前field:map1 *************************ParameterizedType type :java.util.Map<? extends java.lang.String, ? super java.lang.Number>获取到getActualTypeArguments为:? extends java.lang.String上界:class java.lang.String获取到getActualTypeArguments为:? super java.lang.Number上界:class java.lang.Object下界:class java.lang.Number
end ******当前field:map1 *************************begin ******当前field:map2 *************************ParameterizedType type :java.util.Map<? extends java.lang.String, ?>获取到getActualTypeArguments为:? extends java.lang.String上界:class java.lang.String获取到getActualTypeArguments为:?上界:class java.lang.Object
end ******当前field:map2 *************************begin ******当前field:clazz *************************ParameterizedType type :java.lang.Class<?>获取到getActualTypeArguments为:?上界:class java.lang.Object
end ******当前field:clazz *************************begin ******当前field:objList *************************type :interface java.util.List
end ******当前field:objList *************************

我们能够发现,字段的f.getGenericType()绝大部分都是返回的ParameterizedType类型,从而可以继续使用getActualTypeArguments拿到具体类型。看看是不是WildcardType类型像这种private List objList,f.getGenericType()直接就是返回Class: interface java.util.List。Map它可以有多个泛型表达式类型。另外需要说明的一点是:表达式中,如果你没有指定上限,默认都是有上限的:class java.lang.Object,但是下限不会有默认值。

泛型中使用 & (并且)操作符
我们不乏有时候能够看到泛型搭配上 & 的使用方式,比如:
static <R extends Enum & BaseIntEnum> List parse2Enums(…){…}首先说明一点:&不能用于?通配符上(因为通配符不能放在泛型的申明上)&只能放在泛型的声明上。比如类似这种:
public class WildcardTypeTest<T extends Comparable & List & Serializable> { … }
// 或者方法上申明泛型也成
static <R extends Enum & BaseIntEnum> List parse2Enums(…){…}需要注意的是,& 后面只能放置接口,而不能是具体类型。连Object都不行。因此当我们需要泛型的多重约束的时候,可以使用此并且&操作符

但是它不能用于super上,因为Java有规定:
class A< T extends Number> is allowed
but
class A< T super Integer> is not allowed 原因 T不能用于super,只能用extends

  1. TypeVariable(类型变量)
    泛型的类型变量,指的是List< T>、Map< K,V>中的T,K,V等值,实际的Java类型是TypeVariableImpl(TypeVariable的子类;此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,例如 List< T extends Number & Serializable>;其中,& 后必须为接口;
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {//类型对应的上限,默认为Object  可以有多个Type[] getBounds();//获取声明该类型变量实体,// 也就是下边示例,TypeVariableTest<T>中的TypeVariableTestD getGenericDeclaration();//获取类型变量在源码中定义的名称;String getName();// JDK8新增的AnnotatedType[] getAnnotatedBounds();
}

看下边代码:

package com.example.test;import java.io.Serializable;
import java.lang.reflect.*;
import java.util.List;public class TypeVariableTest<T extends Number & Serializable, V> {private T key;private V value;// 显然它本身是个GenericArrayType类型,里面是TypeVariable类型private V[] values;//ParameterizedType 和 TypeVariable的结合private List<T> tList;private String str;private static void printTypeVariable(String fieldName, TypeVariable typeVariable) {for (Type type : typeVariable.getBounds()) {System.out.println("\t\t" + fieldName + ": TypeVariable getBounds " + type);}System.out.println("\t\t定义Class getGenericDeclaration: " + typeVariable.getGenericDeclaration());System.out.println("\t\tgetName: " + typeVariable.getName());}public static void main(String[] args) {Field f = null;try {Field[] fields = TypeVariableTest.class.getDeclaredFields();for (int i = 0; i < fields.length; i++) {f = fields[i];if (f.getName().equals("log")) {continue;}System.out.println("开始 ******当前field:" + f.getName() + " *************************");Type genericType = f.getGenericType();if (genericType instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) genericType;for (Type type : parameterizedType.getActualTypeArguments()) {System.out.println("\t获取ParameterizedType actualType arguments:" + type);if (type instanceof TypeVariable) {printTypeVariable(f.getName(), (TypeVariable) type);}}System.out.println("\t 获取ParameterizedType getOwnerType:" + parameterizedType.getOwnerType());System.out.println("\t 获取ParameterizedType getRawType:" + parameterizedType.getRawType());} else if (genericType instanceof GenericArrayType) {GenericArrayType genericArrayType = (GenericArrayType) genericType;System.out.println("GenericArrayType type :" + genericArrayType);Type genericComponentType = genericArrayType.getGenericComponentType();if (genericComponentType instanceof TypeVariable) {TypeVariable typeVariable = (TypeVariable) genericComponentType;printTypeVariable(f.getName(), typeVariable);}} else if (genericType instanceof TypeVariable) {TypeVariable typeVariable = (TypeVariable) genericType;printTypeVariable(f.getName(), typeVariable);} else if(genericType instanceof Class){System.out.println("type Class:" + genericType);}System.out.println("结束 ******当前field:" + f.getName() + " *************************");System.out.println();}} catch (Exception e) {}}}

输出结果:

开始 ******当前field:key *************************key: TypeVariable getBounds class java.lang.Numberkey: TypeVariable getBounds interface java.io.Serializable定义Class getGenericDeclaration: class com.example.test.TypeVariableTestgetName: T
结束 ******当前field:key *************************开始 ******当前field:value *************************value: TypeVariable getBounds class java.lang.Object定义Class getGenericDeclaration: class com.example.test.TypeVariableTestgetName: V
结束 ******当前field:value *************************开始 ******当前field:values *************************
GenericArrayType type :V[]values: TypeVariable getBounds class java.lang.Object定义Class getGenericDeclaration: class com.example.test.TypeVariableTestgetName: V
结束 ******当前field:values *************************开始 ******当前field:tList *************************获取ParameterizedType actualType arguments:TtList: TypeVariable getBounds class java.lang.NumbertList: TypeVariable getBounds interface java.io.Serializable定义Class getGenericDeclaration: class com.example.test.TypeVariableTestgetName: T获取ParameterizedType getOwnerType:null获取ParameterizedType getRawType:interface java.util.List
结束 ******当前field:tList *************************开始 ******当前field:str *************************
type Class:class java.lang.String
结束 ******当前field:str *************************

可以看出:TypeVariable是可以有多个的。可以使用getBounds拿出来,它返回的是数组, V虽然啥都没写,但是也是有上限:java.lang.Object的
普通类型比如String,它啥都木有~~~~属于Class类型
5. Class(原始/基本类型)
Type的直接子类只有一个,也就是Class,代表着类型中的原始类型以及基本类型。Class —— 反射基石。其意义为:类的抽象,即对“类”做描述:比如类有修饰、字段、方法等属性,有获得该类的所有方法、所有公有方法等方法。同时,Class也是Java类型中最重要的一种,表示原始类型、引用类型及基本类型、数组、注解等。

与泛型有关的类型不能和原始类型统一到Class的原因
产生泛型擦除的原因
原始类型和新产生的类型都应该统一成各自的字节码文件类型对象。但是由于泛型不是最初Java中的成分。如果真的加入了泛型,涉及到JVM指令集的修改,这是非常致命的(简单的说就是Java要向下兼容,所以它是假泛型,不像C#那样)Java 引入泛型擦除的原因是避免因为引入泛型而导致运行时创建不必要的类。那我们其实就可以通过定义类的方式,在类信息中保留泛型信息,从而在运行时获得这些泛型信息。简而言之,Java 的泛型擦除是有范围的,即类定义中的泛型是不会被擦除的。
匿名内部类和父类范型,可以避免范型的擦除
看下边的代码

package com.example.test;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;// 泛型不消失的情况对比
public class Main {private static class HashMapEx<K, V> extends HashMap<K, V> {public HashMapEx() {super();}}public static void main1(String[] args) {// 此处必须用匿名内部类的方式写,如果使用new HashMapEx<String,Integer> 效果同上Map<String, Integer> map = new HashMap<String, Integer>() {};Type type = map.getClass().getGenericSuperclass(); // 获取HashMapEx父类范型HashMap<String, Integer>ParameterizedType parameterizedType = ParameterizedType.class.cast(type);Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 两个类型  一个是K,一个是Vfor (Type typeArgument : actualTypeArguments) {System.out.println(typeArgument.getTypeName()); //String, Integer(使用内部类泛型不消失)}}public static void main(String[] args) {Map<String, Integer> map = new HashMap<String, Integer>();Type type = map.getClass().getGenericSuperclass(); // 获取HashMap父类AbstractMap<K,V>  请注意:此处为<K,V>ParameterizedType parameterizedType = ParameterizedType.class.cast(type);Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 两个类型  一个是K,一个是Vfor (Type typeArgument : actualTypeArguments) {System.out.println(typeArgument.getTypeName()); //k,v(泛型被擦除消失了)}}
}

输出结果:

String
Integer
K
V

getSuperclass 返回直接继承的父类(由于编译擦除,没有显示泛型参数)
getGenericSuperclass:返回直接继承的父类(包含泛型参数) 1.5后提供

    public static void main(String[] args) {// 此处必须用匿名内部类的方式写,如果使用new HashMapEx<String,Integer> 效果同上Map<String, Integer> map = new HashMap<String, Integer>() {};System.out.println(map.getClass().getSuperclass()); //class java.util.HashMapSystem.out.println(map.getClass().getGenericSuperclass()); //java.util.HashMap<java.lang.String, java.lang.Integer>// 但是如果是不带泛型的,两者等价Integer i = new Integer(1);System.out.println(i.getClass().getSuperclass()); //class java.lang.NumberSystem.out.println(i.getClass().getGenericSuperclass()); //class java.lang.Number}

输出结果

class java.util.HashMap
java.util.HashMap<java.lang.String, java.lang.Integer>
class java.lang.Number
class java.lang.Number

Java中如何引入泛型
为了使用泛型又不真正引入泛型,Java采用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,校验类型,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除

Class不能表达与泛型有关的类型
因此,与泛型有关的参数化类型(ParameterizedType)、类型变量类型(TypeVariable)、限定符类型(WildcardType) 、泛型数组类型(GenericArrayType)这些类型编译后全部被打回原形,在字节码文件中全部都是泛型被擦除后的原始类型,并不存在和自身类型对应的字节码文件。所以和泛型相关的新扩充进来的类型不能被统一到Class类中。

与泛型有关的类型在Java中的表示
为了通过反射操作这些类型以迎合实际开发的需要,Java就新增了ParameterizedType, TypeVariable< D >, GenericArrayType, WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型

引入Type的原因
为了程序的扩展性,最终引入了Type接口作为Class和ParameterizedType, TypeVariable, GenericArrayType, WildcardType这几种类型的总的父接口。这样可以用Type类型的参数接受以上五种子类的实参或者返回值类型就是Type类型的参数统一了与泛型有关的类型和原始类型Class

Type接口中没有方法的原因
从上面看到,Type的出现仅仅起到了通过多态来达到程序扩展性提高的作用,没有其他的作用。因此Type接口的源码中没有任何方法。

最后用一个我们最常用的例子:反射获取泛型类型。给出解决方案如下
反射获取类的泛型类型
这个还是非常有用的,比如我们在常用的泛型基类设计中可以这么写

public class BaseDaoImpl<T> implements BaseDao<T> {// 它代表着实际类型private Class<T> beanClass;@SuppressWarnings("unchecked")public BaseDaoImpl() {ParameterizedType parameterizedType=(ParameterizedType)this.getClass().getGenericSuperclass();beanClass=(Class<T>) parameterizedType.getActualTypeArguments()[0];}// 省略具体的操作....
}

再次说明:Class类有两个"雷同"的方法:

//返回直接继承的父类(不显示泛型参数)public native Class<? super T> getSuperclass(); // @since 1.5// 返回直接继承的父类 显示泛型参数public Type getGenericSuperclass();

从执行结果上,更能看出差异:

Student.class.getSuperclass()    class cn.test.Person
Student.class.getGenericSuperclass()    cn.test.Person<cn.test.Test>

总结一下是为了程序的扩展性,最终引入了Type接口作为Class,ParameterizedType,GenericArrayType,TypeVariable和WildcardType这几种类型的总的父接口。这样实现了Type类型参数接受以上五种子类的实参或者返回值类型就是Type类型的参数。
最后再来回顾一下:
List<T ? entends>[] list:这里的T就是TypeVariable,T ? entends就是WildcardType(注意,WildcardType不是Java类型,而是一个表达式),整个List<T ? entends>[]就是GenericArrayType

java Type分类:GenericArrayType TypeVariable WildcardType ParameterizedType Class相关推荐

  1. Java Type类

    文章目录 Type简介 Type分类 1. 原始类型(Class) 2. 参数化类型(ParameterizedType) 3. 类型变量(TypeVariable) 4. 通配符类型(Wildcar ...

  2. Java Type类型详解

    Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的"爹":其中,"所有类型"的描述尤为值得关注.它并不是我们平常工作中 ...

  3. java递归查询分类及分类下所有子分类

    该案例是实际开发中运用,java递归查询分类及分类下所有子分类. 代码走起: 1.jsp页面布局样式这里不再介绍,js业务逻辑展示分类树形结构如下: /*** 商品分类操作*//*** 初始化*/ $ ...

  4. JAVA异常分类和处理

    JAVA异常分类和处理 参考文章: (1)JAVA异常分类和处理 (2)https://www.cnblogs.com/Mr-RanX/p/11279667.html 备忘一下.

  5. Java异常分类和关系

    Java异常分类和结构,包括Throwable.Exception.Runtime Exception等. 还包括unchecked exception.checked exception Java异 ...

  6. Java引用类型分类以及详解

    Java引用类型分类以及详解 - Java引用类型概述 在JVM之中再好的算法,也敌不过一个好烂的程序员.一个程序要想写好有两点:按照开发标准进行.请写有用代码. 而对于垃圾的产生与回收的处理之中,要 ...

  7. java type proposals_Java proposals、Java Type proposals和Java Non-Type proposals区别

    问题背景(可以选择性跳过直接看结论-.-) 最近换了一个Eclipse,在写代码的时候发现代码提示有问题,比如想打this,打出th却不提示this这个整词.于是我便去"首选项->Ja ...

  8. Java Type接口 运行时获取泛型类型

    一.Type接口 Type是所有类型的父接口,他有4个子接口和一个实现类. Class比较常见,它表示的是原始类型.Class类的对象表示JVM中的一个类或接口.每个Java类在JVM里都表现为一个C ...

  9. java type 类型,java中的泛型类型与Type接口

    假设我们定义了一个Room的类,表示一个房间 public classRoom(){ } 由于我们建造好房间是,不知道房间以后的用途,他可能用来住人,也有可能用来放货物,因此需要用到泛型.但是我们可能 ...

最新文章

  1. AtCoder AGC032E Modulo Pairing (二分、贪心结论)
  2. Yum出错Error: Cannot find a valid baseurl for repo: addons
  3. Could not resolve the package 'english_words' in 'package:english_words/english_words.dart'
  4. 深入理解客户的需求至关重要!
  5. python实现50行代码_50行Python代码,教你获取公众号全部文章
  6. linux性能监控常用命令
  7. MySQL树结构查询所有叶子节点
  8. MLAPP————第十四章 核方法
  9. 谈谈我对网站的个人规划
  10. 数据分析师职业分析报告
  11. Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Connections could not b
  12. Multi-University Training Contest L - Wavel Sequence
  13. 系统安全与应用【上】
  14. 阿里面试,问了我乐观锁、悲观锁、AQS、sync和Lock,这个回答让我拿了offer
  15. SEO关键词排名优化教程
  16. 三轮全向移动机器人的控制方法
  17. Android studio案例Android商城
  18. Windows系统通用定时关机命令
  19. 域名解析异常如何解决?快解析轻松实现动态域名解析
  20. 甘肃金昌市“公交一卡通”正式启用

热门文章

  1. P2658 汽车拉力比赛 - 普及+/提高-二分+搜索
  2. unpivot行转列 oracle,Oracle列转行_unpivot
  3. 入手评测:红米9和红米note8哪个好-红米9和红米note8pro参数对比
  4. 项目管理六大阶段 --美国IT项目管理硕士笔记(三)
  5. php红白黑三球_)在一个PPT演示文稿的一页幻灯片中,有两个图片文件,其中图片1把图片2覆盖住了,若要设置为图片2覆盖住图片1,以下最优的操作方法是( )...
  6. 概率分布之Beta分布与Dirichlet分布
  7. Windows电脑常用快捷键
  8. 前端html标签总结,前端面试准备之html知点总结(一)
  9. mac下chrome浏览器查看网络源代码,及请求头信息
  10. oracle通配符和运算符