Java的反射类型加入泛型后,仅仅Class不足以描述数据的类型,比如List\类型的数据,其Class类型为List.class,但其类型包含泛型参数,所以java引入了Type类型来描述泛型类型。除了泛型之外,还有数组格式的数据,它的类型也包括两部分,一部分是数组对象本身的类,另一部分是数组中数据的类型。本文将详细介绍JavaType中的各种类型,并分析如何使用这些类型。类型介绍类型是Java编程语言中所有类型的通用高层接口,即Java中所有“类型”的接口。官方定义如下\>官方文档:Type是Java编程语言中所有类型的通用超接口。这些包括原始类型、参数化类型、数组类型、类型变量和原始类型。官方这样的描述有??点难以理解,这里我画个图来解释一下。类型实际上是和泛型一起出现的。可以说Type就是为了支持泛型。在泛型出现之前,我们可以通过Class来确定一个对象的类型,比如ClassAA,那么A的类型就是ClassA;泛型出现后,显然一个对象的类型不能通过Class来唯一确定,比如List\A,A的Class是List,但是A的类型显然不仅仅是List,它是一个类型由ListofClasstype+ClassAofTypeVariables组合确定。\>类型变量是在类、接口、方法和构造函数体中用作类型的非限定标识符。Type类型可以分为两类:包含TypeVariables的类型和不包含TypeVariables的类型:不包含TypeVariable:包含基本数据类型(int、long等)、基本Class(如Object,不包含泛型)类);containsTypeVariable,根据包含的TypeVariable分为以下几类:ParameterizedType:表示参数化类型,如List\,泛型参数已经指定;GenericArrayType:表示元素类型为参数化类型或类型变量的数组类型,如List\[][];WildcardType:表示一个通配符类型的表达式公式,如List\,List\,List\。在继续介绍Type之前,我们需要先介绍一下java的泛型机制:泛型是JavaSE1.5的新特性,泛型的本质是参数化类型,也就是说要操作的数据类型指定为一个参数。这种参数类型可用于创建类、接口和方法,分别称为泛型类、泛型接口和泛型方法。Java语言引入泛型的好处是安全、简单。泛型的优点是在编译时检查类型安全,所有的转换都是自动和隐式的,以提高代码重用。通用信息只存在于代码编译阶段。在进入JVM之前,与泛型相关的信息将被擦除。技术术语称为类型擦除。参数化类型ParameterizedType写法如下:C\,其中C为Class类型,\为Type,先列举几个参数化Legal类型定义:Seq\Seq\\>Seq\.Zipper\Pair\ParameterizedType接口方法介绍:返回值方法namedescriptioninformationType[]getActualTypeArguments()参数化类型中的TypeVariable参数类型,如List\返回String.class,List\\>返回List\<\TypegetOwnerType()获取当前Type所属的Type。比如对于O\.I\中的I\类型,会返回O\TypegetRawType()得到当前Type的Class,比如List\ReturnList.class\>ParameterizedType表示参数化类型,例如Collection\。参数化类型是在反射方法首次需要时创建的,如本包中所指定。创建参数化类型p时,解析p实例化的泛型类型声明,并递归创建p的所有类型参数。参见TypeVari能够详细了解类型变量的创建过程。重复创建参数化类型没有任何效果。实现此接口的类的实例必须实现一个equals()方法,该方法使共享相同泛型类型声明并具有相同类型参数的任何两个实例相等。数组类型GenericArrayType写法如下:C\[],其中C为Class类型,\为Type。首先列出数组泛型类型的几种合法定义:List\[]List\\>[][]返回值方法名描述信息TypegetGenericComponentType()数组元素类型,如List\[]返回List\注意:\<\>不能出现在数组的初始化中,即\<\>不能出现在新数组后面,否则javac传不过去,但是完全可以作为引用变量或者方法的参数。不包含泛型类型的数组(如String[])本节不介绍,下面介绍。\>GenericArrayType表示其组件类型为参数化类型或类型变量的数组类型。表达式包括以下三种类型:“?”、“?extendsType”、“?superType”,其中Type可以是WildcardType、GenericArrayType、ParameterizedType、Class。\>WildcardType表示通配符类型表达式,如?、?扩展数字,或者?superInteger.WildcardType接口的方法和介绍如下。返回值方法名描述信息Type[]getLowerBounds()返回通配符Type的下限类型,本阶段返回值长度为1Type[]getUpperBounds()返回通配符Type的上限类型,本阶段返回值长度为1BasicClass,基本数据类型和数组通过反射获取基本Class和基本数据类型。这里就不详细介绍了。接下来,我将重点介绍数组类型。java的数组类型是由虚拟机生成的,虚拟机生成的数组类型的名字一般类似于“class[[Ljava.lang.String;”,注意“[[”表示一个二-维数组。那么如何获取数组中的元素类型呢?java.lang.Class包提供了如下接口查询:返回值方法名描述信息Class\componentType()如果类型是数组类型,则返回数组中元素的类型,否则返回null\>componentType():返回这个类的组件类型,如果它描述的是数组类型,否则返回null。如何获取字段或参数的Type信息在使用java程序的过程中,我们接触最多的类型只有Class,比如泛型、Array类型,通常只能通过反射获取。获取字段的通用信息。在下面的程序中,我们首先定义了一个自定义类TestParameterizedType,它只包含一个字段List\字段,然后在另一个单独的测试实例中尝试通过反射获取字段相关信息。通过field.getType()我们得到字段的类型。通过field.getGenericType()我们得到了该字段的通用信息。publicclassReflectParameterizedTypeTest{publicstaticclassTestParameterizedType{privateList\字段;}@TestpublicvoidtestIntType()throwsNoSuchFieldException{Class\clazz=TestParameterizedType.class;Fieldfield=clazz.getDeclaredField("field"");//这里获取字段的实际Class类型Class\clazzType=field.getType();System.out.println("Fieldtype:"+clazzType.getName());//这里获取字段的泛型类型TypegenericType=field.getGenericType();System.out.println("字段泛型类型:"+field.getGenericType().getTypeName());}}获取方法参数的泛型信息和字段的获取方式类似,方法可以通过Method.getGenericParameterTypes()获取所有参数的泛型信息,无法获取运行时变量的泛型信息,具体原因,参考了java中的泛型擦除原理,本文大部分内容参考了java官方文档,点此可直达JAVA15官方文档地址,我是鱼虎神,欢迎大家关注我的微信公众号