如果使用
final字节码,效率不会明显提高,因为Java字节码编译器通常不会进行优化。效率奖励(如果有)将在JIT编译器1生成的本机代码中。
从理论上讲,使用会
final为JIT编译器提供提示,以帮助其进行优化。实际上,最新的HotSpot
JIT编译器可以忽略提示,从而做得更好。例如,现代的JIT编译器通常执行全局分析,以找出给定的方法调用是否是在应用程序当前加载的类的上下文中对叶方法的调用。这种分析比您的
final提示更准确,并且运行时甚至可以检测到何时加载了使分析无效的新类……并为受影响的代码重做分析和本机代码生成。
使用以下其他语义后果
final:
- 将变量声明为as
final
可以防止意外更改它。(并向读者表达您的意图。) - 将方法声明为
final
防止在子类中重写。 - 将类声明为as
final
可以防止完全子类化。 - 将字段声明为as
final
阻止子类对其进行更改。 - 将字段声明为
final
对线程安全有重要影响;参见JLS 17.5。
在适当的情况下,这些都可以。但是,很明显,它们通过创建子类来限制重用的选项。在决定是否使用时需要考虑这一点
final。
因此,优良作法是用来
final(广义上)表达您的设计意图,并实现所需的其他语义效果。如果
final仅将其用作优化提示,那么您将不会取得太大成就。
有一些例外情况
final可能 导致某些平台上的性能有所改善。
在某些情况下,将字段声明为会
final
更改字节码编译器处理该字段的方式。我在上面举了一个例子。另一个是“常量变量”的情况下(JLS 4.12.4),其中一个static final
字段的值 将被 由字节代码编译器都在当前类,并且在其它类内联,这可能会影响代码的观察到的行为。(例如,引用常量不会触发类初始化。因此,添加afinal
可能会 更改类初始化的顺序。)可以想象,将字段或局部参数声明为
final
可能允许进行JIT编译器的次优优化,否则该优化将无法完成。然而,可以声明为final的任何领域 可能 也被推断为通过JIT编译器有效决赛。(尚不清楚JIT编译器实际上会执行此操作,以及是否会影响生成的本机代码。)
但是,底线保持不变。您应该使用它
final来表达设计意图,而不是作为优化提示。
1-此答案假定我们正在谈论具有良好JIT或AOT编译器的最新JVM。1)最早的Sun Java实现根本没有JIT编译器。2)早期的Android
Java实现使用的编译器在优化方面做得很差。实际上,早期的Android开发人员文档建议采取各种源代码级的微优化来弥补这一不足。此建议已被删除。



