管中窥虎
在学习 java 1.5 的过程中,我使用了 sun 公布的 tutorial ,这份文档写的比较详尽易明,但是对于想快速了解 tiger 而且具有较好 java 基础的人来说,大篇幅的英文文档是比较耗时间和非必需的,所以我将会归纳这份文档的主要内容,在保证理解的底线上,尽力减少阅读者需要的时间。
在以下地址可以进入各新增语言特色介绍以及下载相关文档(若有)。
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html
泛型让你在类这一层次上进行抽象。看看例子:
第 3 句的转换类型有点麻烦吧~?编译器只能保证容器类里放的是 Object 对象,要使用他们只能这样去转换。而且这样的转换也并不是完全安全的,程序员可能犯错误,容器里的对象未必是他以为的对象。有没有办法显式地表达出程序员的意图,将该容器限制为只能保存特定类型的对象?这正是 generic -泛型的核心用意。
这样子我们就声明了一个只放 Integer 的 List ,我们说 List 是一个 generic Interface ,接收了一个类型参数,在上例中就是 Integer 。在初始化的时候,同样的也指定了这个类型参数。
要注意这些工作的效果不是仅仅把原来的第 3 句的转换工作省掉,而是由此让编译器确保了这个 List 在程序的任何位置任何时候都用以存放正确的类型,而原来的类型转换仅仅告诉我们在这一单点处程序员自己认为的类型。
泛型由此为程序,尤其是大型程序,带来了可读性和健壮性。
尖括号内的标识符就是一个类型形式参数。类似于方法的参数,当你使用的时候就替换一个实际参数进去,只不过这个参数是个类型。在上面的例子中,我们就替换了一个
在这里稍微说一下命名的规范,定义泛型中的形式参数时,使用简洁有力又具有启发性的名字,如果可以的话用单个字母更好。避免使用小写,以免和普通的方法参数混淆。
看看以下的例子语句合法吗?
第 2 句是行不通的,看看以下的语句:
简而言之就是,原有类型的继承关系是不会反映到对应的泛型上来,在上述情况下,任何两个泛型类型都不存在继承关系。那么,习惯了面向接口编程的我们怎样去适应这种严格的使用限制呢?
假如我们要用一个方法把一个容器内的元素都 print 出来,可以用这样的代码来实现 :
如果我们用新的泛型和新的
事实是,新的代码的使用范围非常有限,因为 Collection < Object > 就只是一个放 Object 的容器泛类,它不是 任何其他 Collection 泛类的父类!真正担任这个角色的是:
Collection < ? >
这个问号代表了未知, Collection < ? > 的元素可以是任何类型,这就是通配类型。
现在我们可以这样写:
注意在循环里面,可以把元素赋值给一个 Object 类型,因为无论 c 里放的是什么,它肯定是一个 Object ,但向 c 里放置对象则是不安全的,因为不知道 c 的泛型是什么。如下面这样是不行的:
add() 方面接纳的是泛型的形式参数里描述的类型(或它的子类,希望你对此不感到混乱,呵呵。),然而此时我们只看到一个问号,我们不知道它的类型参数是什么,当然就不能放置对象进去。唯一一个例外是 null ,它是任何一个类型的对象集的一分子。
省去一些说明性的代码,以我们熟悉的几何图形家族例子来说明:
一个 List<T> ,如果 T 是 Shape 的子类,那么这个 List 都可以被上面这个方法接纳为参数,这个就是受限的通配符。 Shape 就称为这个通配符的上限。
看看下面的代码,怎样?
如上的方法依然是不行的,因为我们只知道
总结起来,我们要了解的事情有:
l 泛型的用意
l 泛型的几种形式(普通,通配符,受限通配符)
l 泛型与继承关系一起使用时的易错倾向,尤其是向泛型容器添加元素的情况。
posted on 2006-08-22 11:11 Binary 阅读(508) 评论(1) 编辑 收藏 所属分类: j2se
Powered by: BlogJava Copyright © Binary