一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。泛型的目的是编写更通用的代码,要使代码能够应用于“某种不具体的类型”,而不是一个具体的接口或类。
这就是Java SE5的重大变化之一:泛型的概念。泛型实现了参数化类型的概念,使代码可以应用于多种类型。“泛型”这个术语的意思是:“适用于许多许多种类型”。泛型在编程语言中出现时,其最初的目的是希望类或方法能够具备最广泛的表达能力。
简单泛型
有许多原因促成了泛型的出现,而最引人注目的一个原因,就是为了创造容器类。泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。
类型参数的好处
在Java 中增加泛型类之前,泛型程序设计是用继承 实现的。ArrayList 类只维护一个 Object 引用的数组:
public class ArrayList //before generic classes
{
private Object[] elementData;
...
public Object get(int i) {. . . }
public void add(Object o) {. . . }
}
这种方法有两个问题。当获取一个值时必须进行强制类型转换。
ArrayList files = new ArrayList();
. . .
String filename = (String)files.get(0);
此外,这里没有错误检查。可以向数组列表中添加任何类的对象。
files.add(new File(". . . "));
对于这个调用,编译和运行都不会出错。然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误。
泛型提供了一个更好的解决方案:类型参数 (type parameters)。ArrayList 类有一个类型参数用来指示元素的类型:ArrayList<String> files = new ArrayList<String>();
这使得代码具有更好的可读性。人们一看就知道这个数组列表中包含的是 String 对象。
现在,编译器可以进行检查,避免插入错误类型错误类型的对象。例如files.add(new File(". . . ")); //can only add String objects to an ArrayList<String>
是无法通过编译的。出现编译错误比类在运行时出现类的强制转换异常要好得多。
这使得代码具有更好的可读性。人们一看就知道这个数组列表中包含的是 String 对象。
类型参数的魅力在于:使得程序具有更好的可读性和安全性。