我们可以看到,在这个简单的例子中,我们在定义aList的时候指明了它是一个直接受 Integer类型的ArrayList,当我们调用aList.get(0)时,我们已经不再需要先显式的将 结果转换成Integer,然后再赋值给myInteger了。而这一步在早先的Java版本中是必须 的。也许你在想,在使用Collection时节约一些类型转换就是Java泛型的全部吗?远不 止。单就这个例子而言,泛型至少还有一个更大的好处,那就是使用了泛型的容器类变 得更加健壮:早先,Collection接口的get()和Iterator接口的next()方法都只能返回 Object类型的结果,我们可以把这个结果强制转换成任何Object的子类,而不会有任何 编译期的错误,但这显然很可能带来严重的运行期错误,因为在代码中确定从某个 Collection中取出的是什么类型的对象完全是调用者自己说了算,而调用者也许并不清 楚放进Collection的对象具体是什么类的;就算知道放进去的对象“应该”是什么类, 也不能保证放到Collection的对象就一定是那个类的实例。现在有了泛型,只要我们定 义的时候指明该Collection接受哪种类型的对象,编译器可以帮我们避免类似的问题溜 到产品中。我们在实际工作中其实已经看到了太多的ClassCastException,不是吗?
泛型的使用从这个例子看也是相当易懂。我们在定义ArrayList时,通过类名后面的<>括 号中的值指定这个ArrayList接受的对象类型。在编译的时候,这个ArrayList会被处理 成只接受该类或其子类的对象,于是任何试图将其他类型的对象添加进来的语句都会被 编译器拒绝。
那么泛型是怎样定义的呢?看看下面这一段示例代码:(其中用E代替在实际中将会使用 的类名,当然你也可以使用别的名称,习惯上在这里使用大写的E,表示Collection的元 素。)
public class TestGenerics {
Collection col;
public void doSth(E elem) {
col.add(elem);
// ...
}
}
在泛型的使用中,有一个很容易有的误解,那就是既然Integer是从Object派生出来的, 那么ArrayList当然就是ArrayList
|