关于java:java基础之反射类型Type

7次阅读

共计 4449 个字符,预计需要花费 12 分钟才能阅读完成。

Java 在退出泛型之后,仅仅 Class 曾经不足以形容数据的类型了,比方 List\<String\> 类型的数据,其 Class 的类型为 List.class,然而其类型蕴含了泛型参数,所以 java 引入了 Type 类型来形容泛型类型。除了泛型类型,还有数组格局的数据,其类型也蕴含两局部,一部分是数组对象自身的 class,另外一部分是数组中数据的类型。本文会具体介绍 JavaType 中的各种类型,剖析这些类型的应用办法。

Type 介绍

Type 是 Java 编程语言中所有类型的公共高级接口,也就是 Java 中所有 ” 类型 ” 的接口。官网原话定义如下
\> 官网文档:Type is the common superinterface for all types in the Java programming language. These include raw types, parameterized types, array types, type variables and primitive types.

这样的官网形容有点难懂,此处我画个图解释一下。Type 其实是和泛型一起呈现的,能够说 Type 就是为了反对泛型。

  • 泛型呈现之前,咱们能够通过 Class 来确认一个对象的类型,比方 ClassA A,那么 A 的类型就是 ClassA;
  • 泛型呈现之后,显然不能通过 Class 惟一确认一个对象的类型,比方 List\<ClassA\> A,A 的 Class 是 List,然而 A 的类型显然不仅仅是 List,它是由 Class 类型的 List + TypeVariables 的 ClassA 联结确认的一个 Type。

\> A type variable is an unqualified identifier used as a type in class, interface, method, and constructor bodies.

Type 的类型

Type 能够分为两大类:蕴含 TypeVariables 和不蕴含 TypeVariables 的类型:

  • 不蕴含 TypeVariable:蕴含根本数据类型(int, long 等),根本 Class(如 Object,不蕴含泛型的类);
  • 蕴含 TypeVariable,依照蕴含的 TypeVariable 又分为以下几类:

    • ParameterizedType: 示意一种参数化的类型,如 List\<String\>,泛型的参数曾经指定;
    • GenericArrayType: 示意一种元素类型是参数化类型或者类型变量的数组类型,如 List\<String\>[][];
    • WildcardType: 代表一种通配符类型表达式,比方 List\<?\>, List\<? extends ClassA\>, List\<? super Object\>。

持续介绍 Type 之前,须要先介绍一下 java 的泛型机制:

泛型是 Java SE 1.5 的新个性,泛型的实质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型能够用在类、接口和办法的创立中,别离称为泛型类、泛型接口、泛型办法。Java 语言引入泛型的益处是平安简略。泛型的益处是在编译的时候查看类型平安,并且所有的强制转换都是主动和隐式的,以进步代码的重用率。

泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相干的信息会被擦除掉,专业术语叫做类型擦除。

参数化类型 ParameterizedType

参数化类型的写法如下:C\<T1,…,Tn\>,其中 C 是 Class 类型,\<T1,…,Tn\> 是 Type,先列几个参数化类型的非法定义:

Seq\<String\>
Seq\<Seq\<String\>\>
Seq\<String\>.Zipper\<Integer\>
Pair\<String,Integer\>

ParameterizedType 类型的接口办法介绍:

返回值 办法名称 形容信息
Type[] getActualTypeArguments() 参数化类型中的 TypeVariable 参数类型,如 List\<String\> 返回 String.class, List\<List\<\<String\>\> 返回 List\<\<String\>
Type getOwnerType() 获取以后 Type 所属的 Type,比方对于 O\<T\>.I\<S\> 中的 I\<S\> 类型,会返回 O\<T\>
Type getRawType() 获取以后 Type 的 Class,如 List\<String\> 返回 List.class

\>ParameterizedType represents a parameterized type such as Collection\<String\>.A parameterized type is created the first time it is needed by a reflective method, as specified in this package. When a parameterized type p is created, the generic type declaration that p instantiates is resolved, and all type arguments of p are created recursively. See TypeVariable for details on the creation process for type variables. Repeated creation of a parameterized type has no effect. Instances of classes that implement this interface must implement an equals() method that equates any two instances that share the same generic type declaration and have equal type parameters.

数组类型 GenericArrayType

数组泛型类型的写法如下:C\<T\>[],其中 C 是 Class 类型,\<T\> 是 Type,先列几个数组泛型类型的非法定义:

List\<String\>[]
List\<Seq\<String\>\> [][]
返回值 办法名称 形容信息
Type getGenericComponentType() 数组元素的类型,如 List\<String\> []返回 List\<String\>

留神:\<\> 不能呈现在数组的初始化中,即 new 数组之后不能呈现 \<\>,否则 javac 无奈通过。然而作为援用变量或者办法的某个参数是齐全能够的。不蕴含泛型的数组本节不做介绍(如 String[]),下文中会进行介绍。
\>GenericArrayType represents an array type whose component type is either a parameterized type or a type variable.

通配符类型 WildcardType

通配符类型何其字面意思雷同,其泛型类型不再是一个具体的类,而是一个通配符表达式,表达式蕴含以下三种:”?”,”? extends Type”, “? super Type”,其中 Type 能够为 WildcardType,GenericArrayType,ParameterizedType,Class.
\>WildcardType represents a wildcard type expression, such as ?, ? extends Number, or ? super Integer.

WildcardType 接口的办法和介绍如下.

返回值 办法名称 形容信息
Type[] getLowerBounds() 返回通配 Type 的上限类型,现阶段返回值的长度为 1
Type[] getUpperBounds() 返回通配 Type 的下限类型,现阶段返回值的长度为 1

根本 Class、根本数据类型和数组

通过反射获取根本的 Class 和根本数据类型此处就不具体介绍了,接下来会重点介绍一下数组类型。java 的数组类型由虚拟机生成,虚拟机生成的数组类型的名称个别相似于 ”class [[Ljava.lang.String;”,留神其中的 ”[[“ 示意是二维数组。那么如何获取数组中的元素类型呢?java.lang.Class 包中提供了以下接口查问:

返回值 办法名称 形容信息
Class\<?\> componentType() 如果类型是数组类型,返回数组中元素的类型,否则返回 null

\>componentType():Returns the component type of this Class, if it describes an array type, or null otherwise.

如何获取字段或参数的 Type 信息

平时应用 java 程序的过程中,咱们接触到的最多的类型只有 Class,像泛型类型和数组类型,通常只有通过反射能力获取到。

获取字段的泛型信息

如下程序中,咱们首先定义了一个自定义的类 TestParameterizedType,只蕴含一个字段 List\<String\> field,而后咱们在另外一个单测实例中尝试通过反射获取 field 的相干信息。通过 field.getType()咱们获取到了 field 的类型。通过 field.getGenericType()咱们获取到了 field 的泛型信息。

public class ReflectParameterizedTypeTest {

    public static class TestParameterizedType {private List\<String\> field;}
    
    @Test
    public void testIntType() throws NoSuchFieldException {
        Class\<?\> clazz = TestParameterizedType.class;
        Field field = clazz.getDeclaredField("field");

        // 此处获取到字段的理论 Class 类型
        Class\<?\> clazzType = field.getType();
        System.out.println("Field type:" + clazzType.getName());

        // 此处获取到字段的泛型类型
        Type genericType = field.getGenericType();
        System.out.println("Field generic type:" + field.getGenericType().getTypeName());
    }
}

获取办法参数的泛型信息

相似于字段的获取形式,办法能够通过 Method.getGenericParameterTypes() 获取所有参数的泛型信息。

获取运行时变量的泛型信息

不可能,具体起因参考 java 的泛型擦除原理。

本文大多数内容参考了 java 官网文档,点此中转 JAVA15 官网文档地址

我是御狐神,欢送大家关注我的微信公众号

本文最先公布至微信公众号,版权所有,禁止转载!

正文完
 0