来源:百度文库 编辑:神马文学网 时间:2024/04/28 19:06:02
此系列文章译自SUN的泛型编程指南, 看不懂译文的请看原文
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
一、绪言
JDK1.5对JAVA语言进行了做了几个扩展,其中一个就是泛型。
本指南旨在介绍泛型。如果你熟悉其它语言的构造类似的东西,特别是C++的模
板(template),你会很快发现它们之间的相同点及重要的不同点;如果你在其他
地方没看到过类似的东西,那反而更好,那样你就可以开始全新的学习,用不着去忘
掉那些(对JAVA泛型)容易产生误解的东西。
泛型允许你对类型进行抽象。最常见的例子是容器类型,比如那些在Collection
层次下的类型。
下面是那类例子的典型用法:
List myIntList = new LinkedList();//1
myIntList.add(new Integer(0));//2
Integer x = (Integer) myIntList.iterator().next();//3
第3行里的强制类型转换有点烦人,程序通常都知道一个特定的链表(list)里
存放的是何种类型的数据,但却一定要进行类型转换。编译器只能保证迭代器返回的
是一个对象,要保证对Integer类型变量的赋值是类型安全的话,必须进行类型转换。
类型转换不但会引起程序的混乱,还可能会导致运行时错误,因为程序员可能会
犯错误。
如果程序员可以如实地表达他们的意图,即标记一个只能包含特定数据类型的链
表,那会怎么样呢?这就是泛型背后的核心思想。下面是前面代码的泛型写法:
List
myIntList = new LinkedList();//1‘
myIntList.add(new Integer(0));//2‘
Integer x = myIntList.iterator().next();//3‘
请注意变量myIntList的类型声明,它指明了这不仅仅是一个任意的List,还
是一个Integer类型的List,写作List。我们说List是一个接受类型(在
这个例子是Integer)参数的泛华的接口,在创建链表对象的时候,我们也指定了一个
类型参数。
另外要注意的是在第3‘行的类型转换已经不见了。
现在你可能会想,我们所做的全部都是为了把混乱消除。我们没有在第3行把类
型转换为Integer,而是在第1‘行加了Integer类型参数;非也非也,这里面差别很
大,编译器现在能够在编译期间检测程序的类型正确性。当我们把myIntList声明为
类型List的后,就意味着变量myIntList在何时何地的使用都是正确的,
编译器保证了这一点。相反,类型转换只是告诉我们程序员认为它在程序的某个地方
是正确的。
实际的结果是,程序(特别是大型的程序)的可读性和健壮性得到了提高。
免费linux公开课,,现在报名!
二、定义简单的泛型
下面是java.util包里的List和Iterator接口定义的一个小小的引用:
public interface List{
void add(E x);
Iterator iterator();
}
public interface Iterator{
E next();
boolean hasNext();
}
除了尖括号里的东西,这里所有的都应该很熟悉了。那是List和Iterator接口
的规范类型参数的声明。
类型参数可以用在任何的泛型声明中,就像使用普通的类型一样(虽然有一些很
重要的限制;看第7部分)。
在绪言中,我们看到了List泛型声明的调用,比如List。在调用里面
(通常称为参数化类型),所有出现规范类型参数(这里是E)的全部都用实际的类型
参数(这里是Integer)所代替。
你可以想象成List代表所有E都用Integer代替了的List:
public interface IntegerList{
void add(Integer x)
Iterator iterator();
}
这种想法是有所帮助的,但也会造成误解。
它是有所帮助的,是因为参数化类型List有看起来像这种扩展的方法。
它会造成误解,是因为泛型的声明实际上不会像那样去扩展;在源代码中、二进制
文件中、硬盘和内在里,都没有代码的多个拷贝。如果你是一个C++程序员,你会明白
这跟C++的模板(template)很不同。
泛型声明是一次编译,永远使用,它会变成一个单独的class文件,就像一个普通
的类或接口声明。
类型参数跟用在方法或构造函数里的普通的参数类似,就像一个方法具有描述它运
算用到的值的类型的规范值参一样,泛化声明具有规范类型参数。当一个方法被调用的
时候,实际的参数将会被规范参数所代替而对方法求值。当一个泛化声明被调用的时候,
实际类型参数将会代替规范类型参数。
命名惯例要注意的一个地方。我们建议你用一些简炼(如果可以的话只用一个字
符)但却映眼的名字作为规范类型参数名。在那些名字中最后避免小写字母,这样可
以很容易把规范类型参数和普通的类或接口区分开来。就像前面的例子一样,很多容
器类型使用E。我们将会在后面的例子里看到其他的惯例。
免费linux公开课,,现在报名!
三、泛型和子类化
http://xoj.blogone.net
我们来测试一下对泛型的理解,下面的代码是否正确呢?
List ls = new ArrayList();//1
List