文档

Java™ 教程
隐藏目录
定义简单的泛型
导航:奖励
课程:泛型

定义简单的泛型

以下是包java.util中接口ListIterator的定义的一小部分:

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

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

这段代码应该都很熟悉,除了尖括号里的部分。这些是接口ListIterator形式类型参数的声明。

类型参数可以在泛型声明中的许多地方使用,就像你使用普通类型一样(虽然有一些重要的限制;参见详细说明部分)。

在介绍中,我们看到了泛型类型声明List调用,比如List<Integer>。在调用(通常称为参数化类型)中,形式类型参数(在这个例子中是E)的所有出现都被实际类型参数(在这个例子中是Integer)替换。

你可以想象List<Integer>代表的是一个List的版本,其中EInteger统一替换:

public interface IntegerList {
    void add(Integer x);
    Iterator<Integer> iterator();
}

这种直觉可能有帮助,但也是误导的。

它是有帮助的,因为参数化类型List<Integer>确实有看起来像这个展开的方法。

它是误导的,因为泛型的声明实际上永远不会以这种方式展开。代码没有多个副本 - 源代码中没有,二进制代码中没有,磁盘上没有,内存中也没有。如果你是C++程序员,你会明白这与C++模板非常不同。

泛型类型声明只会被编译一次,并且变成一个单独的类文件,就像普通的类或接口声明一样。

类型参数类似于方法或构造函数中使用的普通参数。就像方法有描述它所操作的值类型的形式值参数一样,泛型声明有形式类型参数。当调用方法时,实际参数会替换形式参数,并且方法体被计算。当调用泛型声明时,实际类型参数会替换形式类型参数。

关于命名约定的说明。我们建议您为形式类型参数使用简洁(如果可能的话,使用单个字符)但富有表现力的名称。最好避免在这些名称中使用小写字符,以便轻松区分形式类型参数和普通类和接口。许多容器类型使用E,表示元素,就像上面的例子中一样。我们将在以后的例子中看到一些其他的约定。


上一页:介绍
下一页:泛型和子类型