定义简单泛型
以下是接口List
和Iterator
包中定义的一小段摘录java.util
:
public interface List <E> {
void add(E x);
Iterator <E> iterator();
}
public interface Iterator <E> {
E next();
boolean hasNext();
}
这个代码应该都很熟悉,除了尖括号中的东西。这些是接口和形式类型参数的声明。List
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 ++模板非常不同。
泛型类型声明一次性编译,并转换为单个类文件,就像普通的类或接口声明一样。
类型参数类似于方法或构造函数中使用的普通参数。就像方法具有描述其操作的值的形式的形式值参数一样,泛型声明具有形式类型参数。调用方法时,将使用实际参数替换形式参数,并评估方法体。调用泛型声明时,实际的类型参数将替换形式类型参数。
关于命名约定的说明。我们建议您使用简洁(如果可能的话,单个字符),还要使用令人回味的正式类型参数名称。最好避免使用这些名称中的小写字符,这样可以很容易地将正式类型参数与普通类和接口区分开来。E
对于元素,许多容器类型使用如上面的示例中那样。我们将在后面的示例中看到一些其他约定。