复杂是一个比较讨厌的东西,但技术的复杂与政治的复杂却有着本质的区别:后者的目的是愚弄民众,前者却是为了服务用户。
——Fantasy Dog
![](/fckeditor/editor/images/smiley/msn/embaressed_smile.gif)
Generics引进了两个问题,一是针对Exception的,一个则是针对新东西Enum的。
1. Exception
这其实是一个不太复杂的问题,即你不能声明或使用一个parameterized的Exception:
MyException<T> extends Exception
我们知道Exception传递给我们的有效信息实际上就是其类名,比如IOException就是说有个IO的问题——Exception的好处也在于此,你不必花心思去写什么例外信息,创建一个拥有好名字的Exception可以事半功倍。
而Exception的一个特点就是,它是在运行时被捕获的,即编译的时候,编译器无法知道程序会抛出什么样的Exception——否则也没必要用Exception了。
再看Generics,它的核心优点则是提供了编译时的保障,即在编译时进行更多的强制类型检查以减少错误——而java的实现情况是,编译好的代码里,parameter type就消失了。编译器由Generics提供的信息知道了有关的类型,而程序是不可能像程序员一样粗心大意的搞错类型的,于是乎这个parameter type就不再需要了。
结果呢?我们知道 Type<Integer>和Type<Double>是不能相互转化的,在编译时保证了这种相互转化不存在,那么在编译后的代码里就没有必要把这两个东西当作两个不同的类来对待了,事实上在java编译后的环境里,它们就是同一个类。
所以,MyException<Integer>和MyException<Double>在运行时,就是同样的类了。那么对于以下代码:
try{
}catch(MyException<Integer> mi){
}catch(MyException<Double> mo){
}
Java不知道你到底要用哪个catch,在运行时Integer和Double都是不可见的信息了,于是会出错。于是,patameterized Exception干脆就不被允许存在了。
2. Enum
这是一个很丑名昭著的东西:
public abstract class Enum<E extends Enum<E>> {
...
}
研究其字面意思久了对身心有很大的伤害。它想表达的意思大致是:
a. 这是一个类,只能用其子类E做参数
b. 该子类E必须实现某些方法(接口),当然,这些方法定义在Enum这个类里面了
c. 该子类E实现的方法是与E的类型密切相关的。
更多信息在:
总算可以把Generics告一段落了。其实不太多的东西,但看起来确实比较复杂。
有个人对Generics深恶痛绝,于是很是下功夫整理了一篇FAQs,这种精神与意识是很值得人们景仰并学习的: