5

共识似乎是,将成员变量标记为 final 对性能有好处,因为它们永远不需要从主内存重新加载。我的问题是,当很明显变量无法更改时,javac 或 Hotspot 会自动为我执行此操作。例如,javac 将在下面的此类中使'x'最终...

public class MyClass {
   private String x;

   MyClass(String x) {
      this.x = x;
   }

   public String getX() {
      return x;
   }
}

第二点,有没有人提供经验证据表明将成员标记为 final 会使代码运行得更快?在进行远程调用或数据库查找的任何应用程序中,任何好处都肯定可以忽略不计吗?

4

4 回答 4

4

像许多性能“增强”一样,通常最好问一下;什么更容易理解和推理?例如,如果一个字段是最终的,我知道它不会在任何地方更改。这通常会导致更优化的代码,但更重要的是它应该是更可维护的代码。;)

当然,我将任何可以最终确定的字段设为最终字段。就我个人而言,我更希望这final是默认行为,您必须使用关键字 likevar使其可变。

于 2011-04-05T09:23:21.577 回答
2

允许 javac 这样做是一个错误。由于不同的 jar 中可能有可能依赖于正在编译的代码(模块化)的代码,因此在编译时更改代码以进行优化不是一个可行的选择。

至于第二个参数“永远不需要从主内存重新加载”,需要记住大多数实例变量都是缓存的。final只表示不变性,它不保证波动性(volatile == 总是从主内存中获取最新的)。因此在多线程环境中需要 locks 和 volatile 关键字。

至于热点的情况,我不知道,想多听听。final常量可以在编译时内联,从而获得适度的性能提升。参考一个关于 in-lining in java的问题

编辑:

请注意,final表示需要对不可变性持保留态度。它不保证状态不能改变,它只指定可以修改对象引用。final表示原始数据类型的不变性

于 2011-04-05T09:27:40.677 回答
1

AFAIK,他们没有,因此,你会受到轻微的惩罚。然而,这可以使用 IDE 工具(如 Eclipse“Cleanup”功能)自动完成。

于 2011-04-05T09:09:52.903 回答
0

我相信现代 JVM(Hotspot 编译器)确实检测到该值没有改变,因此自己创建参数变量没有性能优势。 final(如果有误,请提供链接或测试用例。)有一个例外:常量(static final)。

但是,这可能与 final方法不同。在这种情况下它可能会提高性能(我不完全确定在什么情况下)。顺便说一句,稍微提高性能的是使函数静态化(如果可能的话)。

我遇到的问题final是它使代码混乱。如果 final 是默认值,那就太好了。

于 2011-04-05T10:53:18.570 回答