Java编译器或者Hotspot虚拟机会自动将不变的变量添加'final'关键字来进行优化吗?

5

普遍认为将成员变量标记为final具有性能优势,因为它们不需要从主内存重新加载。我的问题是,当变量显然不会改变时,javac或Hotspot是否会自动为我完成这个操作。例如,在下面的类中,javac会使'x'成为final吗?

public class MyClass {
   private String x;

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

   public String getX() {
      return x;
   }
}

另外一个问题是,有没有实证证据表明将成员标记为final可以使代码运行更快?在进行远程调用或数据库查询的任何应用程序中,任何好处都肯定是微不足道的。


4
“显然变量不会改变” - 这不是显而易见的,因为Java具有反射能力。 - hoha
FYI:衡量性能提升是困难的:"Performance Anxiety" by Joshua Bloch - Adam Paynter
4个回答

4
许多性能“增强”都可以通过提出一个问题来更好地理解和推理:什么更容易理解和推理?例如,如果一个字段是final的,我知道它不会在任何地方被更改。这通常会导致更优化的代码,但更重要的是它应该是更可维护的代码。 ;)
当然,我会将可以成为final的任何字段都设置为final。个人而言,我更喜欢final成为默认行为,并且您必须使用像var这样的关键字使其可变。

2
+1,如果“final”是默认值,那就太好了,再加上成员变量的“private”。 - WhiteFang34
1
这样,只有在您确实打算这样做时,字段才是可变和可访问的其他类。 - Peter Lawrey
我原则上同意应该编写易读且易于维护的代码,但我并不认为过度使用 final 可以提高可读性。此外,我看到有人仅为了引入 final 而重写代码,例如将以下代码重构:String x; if (coming) { x = "hello"; } else { if (Math.random() > 0.4) { x = "goodbye"; } else { x = "be gone!"; } }final String x = coming ? "hello" : (Math.random() > 0.4 ? "goodbye" : "be gone!"); - barclar
@user329736,我可能会写第二个,尽管我只建议鼓励/默认使用final字段(特别是当不需要其他代码更改时)。在大型方法中,final变量非常有用,此时应将其重构为多个较小的方法。这是我的个人意见。 - Peter Lawrey
1
@barclar,无论您使用(嵌套的)if语句还是条件表达式(也称三元运算符),都与决定将final添加到变量无关。您可以在任何情况下向变量添加final修饰符。关于这个问题,Hotspot优化器添加final修饰符没有意义。final修饰符唯一的潜在好处是提示该变量永远不会改变,因此当优化器检测到该变量永远不会改变时,它不需要添加有关已经检测到的内容的提示。 - Holger

2
允许javac这样做将是一个大错。因为可能有不同的jar文件中的代码依赖于编译的代码(模块化),为了优化而在编译时更改代码并不可行。
至于第二个参数“永远不需要从主存储器重新加载”,需要记住大多数实例变量都被缓存。final仅表示不可变性,它不能保证易失性(volatile == 总是从主存储器获取最新)。因此,在多线程环境中需要锁和volatile关键字。
至于hotspot的情况,我不清楚,希望能听到更多关于它的信息。final常量可以在编译时内联,从而允许适度的性能提升。参考Java内联问题 编辑:请注意,final表示不可变性需要谨慎对待。它不能保证状态不会改变,它只指定对象引用可以被修改。final表示原始数据类型的不可变性。

1
据我所知,它们不会这样做,因此您会受到轻微的惩罚。然而,可以使用IDE工具(如Eclipse的“清理”功能)自动完成此操作。

0

我相信现代JVM(Hotspot编译器)会检测到值不会改变,因此在使参数变量final时不会有性能优势。(如果这是错误的,请提供链接或测试用例。)唯一的例外是常量(static final)。

然而,在final 方法的情况下可能会有所不同。在这种情况下,它可能会提高性能(我不完全确定在哪些情况下)。顺便说一句,如果可能的话,使函数静态可以稍微提高性能。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接