定义简单泛型 (Defining Simple Generics)
下面这段代码摘自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)的声明。
类型参数可以在泛型声明中使用,这与您使用普通类型非常相似(尽管有一些重要的限制;请参阅 细则 一节)。
在 导言(上一节) 中,我们看到了泛型类型声明List的调用,例如List<Integer>。在调用(通常称为参数化类型parameterized type)中,所有形式类型参数(在本例中为E)的出现都被实际的类型参数(在本例中为Integer)所替代。
您可能会想到List<Integer>表示List的一个版本,其中E被Integer统一替换:
public interface IntegerList {
void add(Integer x);
Iterator<Integer> iterator();
}
这种直觉虽然有所帮助,但也有误导性。
有帮助是因为参数化类型List<Integer>确实有类似于此扩展的方法。
有误导性是因为泛型的声明从来没有以这种方式扩展过。并没有多个代码副本——源代码中没有,二进制中没有,磁盘中没有,内存中也没有。如果你是C++程序员,你将了解到这与C++模板有很大不同。
泛型类型声明编译一次并且一劳永逸,转变成一个类文件,就像普通的类或接口声明一样。
类型参数类似于方法或构造函数中使用的普通参数。就像方法具有描述其操作的值类型的形式值参数(formal value parameters)一样,泛型声明具有形式类型参数。调用方法时,用实际参数替换形式参数,并计算方法主体。当调用泛型声明时,实际类型参数将替代正式类型参数。
关于命名习惯的说明。我们建议您对形式类型参数使用简洁(如果可能的话使用单个字符)的名称。最好避免使用小写字符,能更容易将形式类型参数与普通类及接口区分开来。许多容器类型使用E,作为元素,如上面的示例所示。我们将在后面的示例中看到一些其他惯例。
本文译自:https://docs.oracle.com/javase/tutorial/extra/generics/simple.html