|
|
final 关键字常常被误用 - 声明类和方法时使用过度,而声明实例字段时却使用不足。本文探究了一些有关有效使用 final 的准则。
如同它的“表亲”- C 中的 const 关键字一样,根据上下文, final 表示不同的东西。 final 关键字可应用于类、方法或字段。应用于类时,意味着该类不能再生成子类。应用于方法时,意味着该方法不能被子类覆盖。应用于字段时,意味着该字段的值在每个构造器内必须 只能赋值一次而且此后该值永远不变。
大多数 Java 文本都适当地描述了使用 final 关键字的用法和后果,但是很少以准则的方式提供有关何时使用 final 及使用频率的内容。根据我的经验, final 非常过度地用于类和方法(通常是因为开发人员错误地相信这会提高性能),而在其用武之地 - 声明类实例变量 - 却使用不足。
似曾相识 - 重新回忆 register 关键字
final 用于优化决定时和 C 中不赞成使用的 register 关键字非常相似。让程序员帮助优化器这一愿望促成了 register 关键字,但事实上,发现这并不是很有用。正如我们在其它方面愿意相信的那样,在作出代码优化决定方面编译器通常比人做得出色,在现在的 RISC 处理器上更是如此。事实上,大多数 C 编译器完全忽略了 register 关键字。早先的 C 编译器忽略它是因为这些编译器根本就不起优化作用;现今的编译器忽略它是因为编译器不用它就能作更好的优化决定。任何一种情况下, register 关键字都没有添加什么性能优势,和应用于 Java 类或方法的 final 关键字很相似。如果您想优化您的代码,请坚持使用那些可以大幅度提高性能的优化,比如使用有效的算法且不执行冗余的计算 - 将循环计算优化留给编译器和 JVM 去做。
[img=100%,1]http://www.ibm.com/i/v14/rules/blue_rule.gif[/img]
 |
[img=100%,4]http://www.ibm.com/i/c.gif[/img]
|
final 字段
final 字段和 final 类或方法有很大的不同,以至于我觉得让它们共享相同的关键字是不公平的。 final 字段是只读字段,要保证它的值在构建时(或者,对于 static final 字段,是在类初始化时)只设置一次。正如较早讨论的那样,对于 final 类和方法,您将总是问自己是否真的 需要使用 final 。对于 final 字段,您将问自己相反的问题 - 这个字段真的 需要是可变的吗?您可能会很惊讶,这个答案为何常常是“不需要”。
final 字段的局限性
final 字段仍然有一些严重的限制。尽管数组引用能被声明成 final ,但是该数组的元素却不能。这意味着暴露 public final 数组字段的或者通过它们的方法将引用返回给这些字段的类(例如,清单 3 中所示的 DangerousStates 类)都不是不可改变的。同样,尽管对象引用可以被声明成 final 字段,而它所引用的对象仍可能是可变的。如果您想要使用 finalList ,例如清单 3 中所示的 SafeStates 类: 字段创建不变的对象,您必须防止对数组或可变对象的引用“逃离”您的类。要不用重复克隆该数组做到这一点,一个简单的方法是将数组转变成
结束语</strong>
要对类、方法和字段有效使用 final ,有一些基本的准则可以遵循。特别要注意的是,不要尝试将 final 用作性能管理工具;要提高您的程序的性能,有更好且约束更少的方法。在反映您程序的基本语义处使用 final :用来指示这些类将是不可改变的或那些字段将是只读的。如果您选择创建 final 类或方法,请确保您清楚地记录您为何这么做 - 您的同事会感激您的。
转自http://www.ibm.com/developerworks/cn/java/j-jtp1029/
|
|