Java 泛型:T[<T>] toArray(T[] a) 中的第一个"T"是什么意思?



我正在使用Eclipse,当我导航List.class的反汇编时,我看到如下:

<T> T[] toArray(T[] a);
  1. 前面的<T>在这里实际上是什么意思?它是返回类型的一部分吗?我猜返回值是T[]

  2. 在什么情况下,一个函数需要声明像<T> T[]作为函数签名?

这定义了一个方法,其中一些类型不是固定的,而是泛型的。

该方法的非泛型版本为

String[] toArray(String[] a);

意味着您提供一个String[]数组并获得一个String[]数组。

给定的方法将String替换为泛型T,这意味着结果类型现在取决于所提供的类型(*),结果数组类型与作为数组参数提供的类型相同。

此处相关的数组类型不必(完全)对应于整个List的泛型类型(List<E>中的E),而是特定于此方法,因此必须使用此方法声明,即<T> T[] toArray(T[] a);中的<T>

那么,把<T> T[] toArray(T[] a);分解成它的各个部分:

  • <T>声明以下方法具有特定于方法的泛型T
  • T[]表示返回值是该泛型类型的数组。
  • toArray(...)命名方法。
  • T[] a声明方法需要一个数组类型的参数。

对于Java泛型,编译器需要在任何给定的方法调用中找到替换T的特定类型,例如

??? myArray = myList.toArray(new String[17]);

在这里,参数给出了信息:提供了String[]数组,期望T[]数组,因此T必须是String,现在编译器知道在结果类型T[]T也必须用String替换,给出String[]结果类型,这意味着???必须是String[]或兼容的,否则你会得到编译器错误。

除了这种基于演绎的类型匹配之外,还有一种(很少使用的)语法用于显式指定泛型类型。那就是

String[] myArray = myList.<String>toArray(new String[17]);

<String>中缀显式地告诉编译器T的替换。在大多数情况下,这种显式规范是多余的,因此您几乎不会在实际代码中看到这种语法。

(*) Java泛型在编译时完全求值,因此声明的泛型效果仅基于编译器看到的类型。例如,在

Object[] myObjectArray = new String[0];
??? myResultArray = myList.toArray(myObjectArray);

???必须是Object[],尽管在运行时,String[]数组将生成。

请记住,泛型背后的思想是在类型上参数化类,并且在实例化类时指定该类型。<T>是类型参数——也就是说,你这样写是为了说明这个类/方法是在运行时指定的某种类型T上参数化的。

相关内容

最新更新