The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
JDK 5.0 introduces several new extensions to the Java programming language. JDK 5.0为Java编程语言引入了几个新的扩展。One of these is the introduction of generics.其中之一就是泛型的引入。
This trail is an introduction to generics. 这是对泛型的介绍。You may be familiar with similar constructs from other languages, most notably C++ templates. 您可能熟悉其他语言的相似构造,最明显的是C++模板。If so, you'll see that there are both similarities and important differences. 如果是这样,你会发现两者既有相似之处,也有重要区别。If you are unfamiliar with look-a-alike constructs from elsewhere, all the better; you can start fresh, without having to unlearn any misconceptions.如果你不熟悉其他地方的相似结构,那就更好了;你可以重新开始,而不必忘记任何误解。
Generics allow you to abstract over types. 泛型允许抽象类型。The most common examples are container types, such as those in the Collections hierarchy.最常见的例子是容器类型,例如集合层次结构中的容器类型。
Here is a typical usage of that sort:下面是这种用法的典型用法:
List myIntList = new LinkedList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = (Integer) myIntList.iterator().next(); // 3
The cast on line 3 is slightly annoying. 第三行的强制转换有点烦人。Typically, the programmer knows what kind of data has been placed into a particular list. 通常,程序员知道什么样的数据被放入了一个特定的列表中。However, the cast is essential. 然而,强制转换至关重要。The compiler can only guarantee that an 编译器只能保证迭代器返回一个Object
will be returned by the iterator. Object
。To ensure the assignment to a variable of type 为了确保Integer
is type safe, the cast is required.Integer
类型变量的赋值是类型安全的,需要强制转换。
Of course, the cast not only introduces clutter. 当然,强制转换不仅带来混乱。It also introduces the possibility of a run time error, since the programmer may be mistaken.它还引入了运行时错误的可能性,因为程序员可能弄错了。
What if programmers could actually express their intent, and mark a list as being restricted to contain a particular data type? 如果程序员能够真正表达他们的意图,并将列表标记为受限于包含特定数据类型,该怎么办?This is the core idea behind generics. Here is a version of the program fragment given above using generics:这是泛型背后的核心思想。下面是上面使用泛型给出的程序片段的一个版本:
List<Integer> myIntList = new LinkedList<Integer>(); // 1' myIntList.add(new Integer(0)); // 2' Integer x = myIntList.iterator().next(); // 3'
Notice the type declaration for the variable 请注意变量myIntList
. myIntList
的类型声明。It specifies that this is not just an arbitrary 它指定这不仅仅是一个任意列表,而是一个整数列表,写入List
, but a List
of Integer
, written List<Integer>
. List<Integer>
。We say that 我们说List
is a generic interface that takes a type parameter--in this case, Integer
. List
是一个通用接口,它接受一个类型参数——在本例中是Integer
。We also specify a type parameter when creating the list object.在创建列表对象时,我们还指定了一个类型参数。
Note, too, that the cast on line 3' is gone.还要注意的是,第3行的强制转换已经消失了。
Now, you might think that all we've accomplished is to move the clutter around. 现在,你可能会认为我们所做的就是把杂乱无章的东西搬来搬去。Instead of a cast to 我们没有在第3行转换为Integer
on line 3, we have Integer
as a type parameter on line 1'. Integer
,而是在第1行使用Integer
作为类型参数。However, there is a very big difference here. 然而,这里有很大的不同。The compiler can now check the type correctness of the program at compile-time. 编译器现在可以在编译时检查程序的类型正确性。When we say that 当我们说myIntList
is declared with type List<Integer>
, this tells us something about the variable myIntList
, which holds true wherever and whenever it is used, and the compiler will guarantee it. myIntList
是用类型List<Integer>
声明的时,这告诉我们一些关于变量myIntList
的信息,无论何时何地使用它,它都是真的,编译器将保证它。In contrast, the cast tells us something the programmer thinks is true at a single point in the code.相比之下,cast告诉我们程序员认为在代码中的某一点是正确的。
The net effect, especially in large programs, is improved readability and robustness.最终的效果,尤其是在大型程序中,是提高了可读性和健壮性。