我从事JDK 5.0代码的编写工作已经有六个月之久了,我认为有必要花一点时间回顾一下我的编码经验,对该软件所介绍的功能进行总结。
增强的for循环
作为无可争议的嬴家,新的for循环无论在何处(几乎在任何地方)都非常好用,因此我激动得不知如何开始描述。当我被迫使用旧式for循环的时候,特别是需要使用索引或需要让迭代程序在循环之外可见的时候,我的内心深处屡屡畏缩。
代码具有很好的可读性,并且给人的感觉一点也不繁杂(例如,索引不需要的代码或增量公开基础实现)。后面一点是新循环的意外收获。试想一下,有如下代码:
String[] names = ...;
for (String name :names) {
// ...
}
您决定把名称类型改为Collection。如何修改代码?
List names = ...;
for (String name : names) {
// ...
}
仅修改一行就可以了。这就是它的独特优点。
注释
显然,我对注释的了解还具有一定局限性,因为它们位于TestNG的核心位置;但是,我坚信注释行将改变我们使用Java构建软件的方式。长期以来,我们在程序中引入元数据一直依靠的是对黑客做出的反应,注释最终将对此问题提供卓越的解决方案。
此外,我有一个感觉,就是使用某些预定义的注释(如@Override)是没有必要的,所以在这一点上我一直没有形成自己的意见。
在未来的若干年里,对我来说一个无法逃避的现实是,我们阅读和编写的大多数Java代码都将包含注释。
静态导入
除了在Retention 和 Target类型中,我几乎不使用它们。至今还没有人能说服我,添加此功能的本来意图(阻止实现接口的反模式,且无需限定就能重用其常量)证明应该引入新的语言功能,这要让时间说话。
我猜想,从某些方面来说,在我日常编程中使用的IDE完全废弃了导入功能,所以我对这一功能已经没有什么感觉了。
可变长度参数
迄今为止,我从来不需要此功能。有时它可能用起来很方便,但是我真的不相信这种功能确保语言中的改变是正确的。
Enum
理论上,我对Enum持肯定的态度,但是我还没有真正把我的代码转换为Enum,所以我不了解它们的使用效果。我相信如果使用它们效果会很好,将使代码更加健壮。
Generic
把最好的留到最后……但是因为本条目有点长,我将把对Generic的讨论留作明天的话题。
Autoboxing
到目前为止,我还从来没有使用过autoboxing功能,因为我对于代码性能失去控制没有明确的感觉。尽管autoboxing是一种未经证明的功能,它用起来方便,并且可以让代码更具有可读性。我想我应该鼓励开发人员在使用autoboxing时为代码做上标记;我敢肯定IDE的开发人员不久也会这样做。
Generic
说在前面的话。
首先,无可置疑,Generic是一个可能使代码更加健壮的可靠概念。因为它具有可执行性,所以通常抛开具体语言对其进行讨论。多年来作为C++委员会的成员,我清楚地感觉到正确使用它们决非易事。
简言之,对Java generics我用下面的话来进行说明:代码比以前健壮,但更加难以阅读。
那么,问题何在?
冗余。
首先,把一般的强制转换需求引入冗余,对此问题我感觉很棘手。例如,为什么不能不编写:
Map accounts = new HashMap(); // no generics
...
Account a = (Account) accounts.get("Cedric");
而编写:
Map m = new HashMap(); // no generics
...
Account a = m.get("Cedric");
来代替,同时让编译器引入一种静默强制转换模式?因为很显然,它是一个我试图从Map中检索的Account类型的对象。
显然,Generic不能完全解决这个问题,只是在一定程度上有帮助而已。可是,在另外一些方面,它们却有害无益:
Map<String, List<Account>> accounts =
new HashMap<String, List<Account>>();
嗨!
该代码不仅难以阅读,而且还未能遵守DRY(Don't repeat yourself)准则。如果我需要在列表<Account> Collection<Account>中更改此映射的值类型,将会发生什么事?我需要替换代码中的所有的此类声明。尽管IDE重构对此有所帮助,仍然需要对相当多的代码进行修改,此类修改甚至有可能对代码的语义产生一定影响。
事实上,创建新对象时没有什么好办法可以避免该语法,但是我要说的是,如果将typedef和Generic一起引入,情况会好的多。
我最初是这种观点。
但是,随着认识的加深,我发现使用typedef解决问题是一个错误的解决方案,因为靠简单添加的方式对使用单独类定义复杂Generic类型没有任何作用。
class AccountMap extends HashMap<String, List&lAccount>> {
...
}
除去扩展实现(很显然是HashMap而不是Map)这种情况,该解决方案可能比引入typedef好一些,因为typedef有其自身的缺陷。
迄今我还没有遇到这种麻烦,但我的建议是:如果编写该类型三次(初始化两次,在代码中使用一次以上)以上,则使用它。
除此缺点外,总体来说我还是相当喜欢Generics的,而且尤其喜欢阅读编写的非常好的TestNG Javadocs。
结束语
对于JDK 5.0的新特性我非常满意。我有幸参与了JSR 175和JSR 201,从而有机会对开发JDK 5.0的新特性作出了自己的贡献。同所有根本性的变革一样,不是所有的新特性都受到大家的欢迎,但随着大多数开发人员发现其中某些特性非常有用,并且还保留了向后兼容性,我认为JDK 5.0向开发更多健壮的Java代码迈出了坚定的一步。
关于作者
Cedric Beust的电子邮箱:cedric@beust.com
博客:http://www.beust.com/weblog/
Cedric Beust是WebLogic Server团队的高级软件开发人员,他在其博客Otaku中提出了J2EE、Java、AOP和软件开发等方面的见解。
原文出处
http://www.theserverside.com/blogs/showblog.tss?id=JDK5Practice |