定义简单泛型

这是包java.util中interfaceListIterator的定义的一小段摘录:

public interface List <E> {
    void add(E x);
    Iterator<E> iterator();
}

public interface Iterator<E> {
    E next();
    boolean hasNext();
}

除了尖括号中的内容外,所有这些代码都应该很熟悉。这些是interfaceListIterator的形式类型参数的声明。

类型参数可以在整个泛型声明中使用,几乎可以在使用普通类型的地方使用(尽管有一些重要的限制;请参见精美打印部分。

在简介中,我们看到了泛型类型声明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用作元素。我们将在后面的示例中看到一些其他约定。