体验 JAVA 5 的新增语言特性
2008-01-05 18:01:01 来源:WEB开发网java 5.0发布了,许多人都将开始使用这个JDK版本的一些新增特性。从增强的for循环到诸如泛型(generic)之类更复杂的特性,都将很快出现在您所编写的代码中。我们刚刚完成了一个基于Java 5.0的大型任务,而本文就是要介绍我们使用这些新特性的体验。本文不是一篇入门性的文章,而是对这些特性以及它们所产生的影响的深入介绍,同时还给出了一些在项目中更有效地使用这些特性的技巧。
简介
在JDK 1.5的beta阶段,我们为BEA的Java IDE开发了一个Java 5编译器。因为我们实现了许多新特性,所以人们开始以新的方式利用它们;有些用法很聪明,而有些用法明显应该被列入禁用清单。编译器本身使用了新的语言特性,所以我们也获得了使用这些特性维护代码的直接体验。本文将介绍其中的许多特性和使用它们的体验。
我们假定您已经熟悉了这些新特性,所以不再全面介绍每个特性,而是谈论一些有趣的、但很可能不太明显的内容和用法。这些技巧出自我们的实际体验,并大致按照语言特性进行了分类。
我们将从最简单的特性开始,逐步过渡到高级特性。泛型所包含的内容非凡丰富,因此占了本文一半的篇幅。
增强的for循环
为了迭代集合和数组,增强的for循环提供了一个简单、兼容的语法。有两点值得一提:
Init表达式
在循环中,初始化表达式只计算一次。这意味着您通常可以移除一个变量声明。在这个例子中,我们必须创建一个整型数组来保存computeNumbers()的结果,以防止每一次循环都重新计算该方法。您可以看到,下面的代码要比上面的代码整洁一些,并且没有泄露变量numbers:
未增强的For: int sum = 0; Integer[] numbers = computeNumbers(); for (int i=0; i < numbers.length ; i++) sum += numbers[i]; 增强后的For: int sum = 0; for ( int number: computeNumbers() ) sum += number;
局限性
有时需要在迭代期间访问迭代器或下标,看起来增强的for循环应该答应该操作,但事实上不是这样,请看下面的例子:
for (int i=0; i < numbers.length ; i++) { if (i != 0) System.out.PRint(","); System.out.print(numbers[i]); }
我们希望将数组中的值打印为一个用逗号分隔的清单。我们需要知道目前是否是第一项,以便确定是否应该打印逗号。使用增强的for循环是无法获知这种信息的。我们需要自己保留一个下标或一个布尔值来指示是否经过了第一项。 这是另一个例子:
for (Iterator<integer> it = n.iterator() ; it.hasNext() ; ) if (it.next() < 0) it.remove();
在此例中,我们想从整数集合中删除负数项。为此,需要对迭代器调用一个方法,但是当使用增强的for 循环时,迭代器对我们来说是看不到的。因此,我们只能使用Java 5之前版本的迭代方法。 顺便说一下,这里需要注重的是,由于Iterator是泛型,所以其声明是Iterator<Integer>。许多人都忘记了这一点而使用了Iterator的原始格式。
注释
注释处理是一个很大的话题。因为本文只关注核心的语言特性,所以我们不打算涵盖它所有的可能形式和陷阱。 我们将讨论内置的注释(SuppressWarnings,Deprecated和Override)以及一般注释处理的局限性。
Suppress Warnings
该注释关闭了类或方法级别的编译器警告。有时候您比编译器更清楚地知道,代码必须使用一个被否决的方法或执行一些无法静态确定是否类型安全的动作,而使用:
@SuppressWarnings("deprecation") public static void selfDestrUCt() { Thread.currentThread().stop(); }
这可能是内置注释最有用的地方。遗憾的是,1.5.0_04的javac不支持它。但是1.6支持它,并且Sun正在努力将其向后移植到1.5中。
Eclipse 3.1中支持该注释,其他IDE也可能支持它。这答应您把代码彻底地从警告中解脱出来。假如在编译时出现警告,可以确定是您刚刚把它添加进来——以帮助查看那些可能不安全的代码。随着泛型的添加,它使用起来将更趁手。
Deprecated
遗憾的是,Deprecated没那么有用。它本来旨在替换@deprecated javadoc标签,但是由于它不包含任何字段,所以也就没有方法来建议deprecated类或方法的用户应该使用什么做为替代品。大多数用法都同时需要javadoc标签和这个注释。
Override
Override表示,它所注释的方法应该重写超类中具有相同签名的方法:
@Override public int hashCode() { ... }