定义简单泛型
这是包java.util
中interfaceList
和Iterator
的定义的一小段摘录:
public interface List <E> {
void add(E x);
Iterator<E> iterator();
}
public interface Iterator<E> {
E next();
boolean hasNext();
}
除了尖括号中的内容外,所有这些代码都应该很熟悉。这些是interfaceList
和Iterator
的形式类型参数的声明。
类型参数可以在整个泛型声明中使用,几乎可以在使用普通类型的地方使用(尽管有一些重要的限制;请参见精美打印部分。
在简介中,我们看到了泛型类型声明List
的调用,例如List<Integer>
。在调用(通常称为参数化类型)中,所有形式形式参数(在这种情况下为E
)都被实际的类型自变量(在本例中为Integer
)替换。
您可能会想到List<Integer>
代表List
的版本,其中E
已被Integer
统一替换:
public interface IntegerList {
void add(Integer x);
Iterator<Integer> iterator();
}
这种直觉可能会有所帮助,但也会引起误解。
这很有用,因为参数化类型List<Integer>
确实确实具有类似于此扩展的方法。
这具有误导性,因为泛型的声明实际上从未以这种方式扩展。没有代码的多个副本-不在源中,不在二进制中,不在磁盘上,也不在内存中。如果您是 C 程序员,您将了解这与 C 模板有很大不同。
泛型类型声明会一劳永逸地编译,并变成单个类文件,就像普通类或interface声明一样。
类型参数类似于方法或构造函数中使用的普通参数。就像方法具有描述其操作的值的类型的形式值参数一样,泛型声明具有形式类型参数。调用方法时,将实际参数替换为形式参数,并评估方法主体。调用泛型声明时,实际的类型参数将代替形式类型参数。
有关命名约定的说明。我们建议您为正式类型参数使用精巧(如果可能,为单个字符)而又令人联想起的名称。最好避免在这些名称中使用小写字母,以便轻松区分形式类型参数与普通类和interface。如上例所示,许多容器类型将E
用作元素。我们将在后面的示例中看到一些其他约定。