@H_502_1@我听说过这种情况,但我找不到确定的在线资源来确认.
@H_404_2@背景:一位同事喜欢让他的局部变量最终.他这样做的原因之一是表现.我的论点是,Java的HotSpot Just In Time编译器会自动检测不变的局部变量,并使它们成为最终变量,因此自己做这个没有性能上的好处.
@H_404_2@请注意,我不是要问局部变量是否是最终的良好编码实践,因为已经有很多(非主题)SO问题.
@H_404_2@编辑:mrhobo对优化整数文字的字节码提出了一个很好的观点.我应该给出一个我正在谈论的代码类型的例子,我的问题是:
Object doSomething(Foo foo) { if (foo == null) { return null; } final Bar bar = foo.getBar(); final Baz baz = this.bazMap.get(bar); return new MyObject(bar,baz); }@H_404_2@您是否认为在这种情况下会发生相同类型的优化,因为bar和baz都标记为final?或者HotSpot是否会自动检测到它们在方法范围内没有发生变化,并将它们视为最终版本? @H_404_2@类似的问题 @H_404_2@> Declaring local variable as final in a loop @H_404_2@>同样的问题,但通过经验(通过查看类文件)得出答案,没有文档参考 @H_404_2@> Do javac or Hotspot automatically add ‘final’ as an optimisation of invariant variables? @H_404_2@>例如变量的相同问题 @H_404_2@> Inlining in Java @H_404_2@>方法的相同问题 @H_404_2@> Does use of final keyword in Java improve the performance? @H_404_2@>类似的问题,对局部变量没有达成共识
解决方法
要理解为什么最终局部变量对于编译器来说完全无趣,编译器工作方式的一些背景将会有所帮助.基本上没有编译器对源代码(或字节码)本身进行操作,而是将它解析为某种中间表示(在应用优化时通常是几种不同的表示).几乎我所知道的每个编译器都使用某种形式的静态单一赋值或短SSA形式作为其中间表示.
@H_404_2@正如名称所说SSA表单基本上意味着每个变量只被赋值一次.为了更清楚,假设我们有以下简单的代码片段:
y = 4 x = 5 y = 6 z = x + y@H_404_2@在SSA表单中,这看起来类似于以下内容:
y_1 = 4 x_1 = 5 y_2 = 6 z_1 = y_2 + x_1@H_404_2@那我们为什么要这样做呢?因为它使得许多编译器优化变得更加容易(例如,看到y的第一次写入可以被消除,因为我们从未读过它)是微不足道的.所以,如果你想要,你可能会看到这个,因为每个变量已经是编译器的最终变量. @H_404_2@PS:循环和分支确实使这更复杂,但我不想在那里过多地讨论 – 维基文章有一个关于如何解决这些问题的简短解释.