Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
以下是软件包 java.util
中接口 List
和 Iterator
定义的片段:
public interface List <E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext(); }
这个代码应该都很熟悉,除了尖括号中的东西。这些是接口 List
和 Iterator
的 formal type parameters (形式类型形参) 的声明。
类型形参可以在整个泛型声明中使用,几乎可以使用普通类型(尽管有一些重要的限制;请参阅 The Fine Print 部分。
在简介中,我们看到了泛型类型声明 List
的 invocations (调用),例如 List<Integer>
。在调用中(通常称为 parameterized type (参数化类型)),所有匹配项的形式类型形参(在本例中为 E
)都被 actual type argument (实际类型实参替换)(在这种情况下,Integer
)。
你可以想象 List<Integer>
代表 List
的版本,其中 E
已被 Integer
统一替换:
public interface IntegerList { void add(Integer x); Iterator<Integer> iterator(); }
这种直觉可能会有所帮助,但也会产生误导。
这很有用,因为参数化类型 List<Integer>
确实具有看起来像这个扩展的方法。
这是误导性的,因为泛型的声明从未以这种方式实际扩展。没有多个代码副本 - 在源代码,二进制代码,磁盘和内存都没有。如果你是 C++ 程序员,你会明白这与 C++ 模板非常不同。
泛型类型声明一次性编译,并转换为单个类文件,就像普通的类或接口声明一样。
类型形参类似于方法或构造函数中使用的普通参数。与方法具有 formal value parameters (形式值参数) 描述其操作的值的类型非常相似,泛型声明具有形式类型形参。调用方法时,actual arguments (实际参数) 将替换形式参数,并计算方法体。调用泛型声明时,实际类型实参将替换形式类型形参。
注意命名规范。我们建议你使用简洁(单个字符,如果可能)但能引起共鸣的的名称作为形式类型形参。最好避免使用这些名称中的小写字符,这样可以很容易地将形式类型形参与普通类和接口区分开来。许多容器类型使用 E
作为元素,如上例所示。我们将在后面的示例中看到一些其他规范。