【问题标题】:Compilation effects of declaring method parameters "final" [duplicate]声明方法参数“final”的编译效果[重复]
【发布时间】:2014-05-30 19:59:34
【问题描述】:

需要将方法参数标记为 final 以允许内部匿名类访问变量,并且是一种有用的编码工具,用于在方法中强制执行某些变量使用约定。

除此之外,还有其他一些与编译相关的动机来使用final-关键字吗?具体来说,它是否为编译器提供了任何提示,以促进某些原本不会执行的特定优化?或者编译器是否足够聪明,可以始终识别变量是否从未被修改过?

例如,我在考虑变量传递到方法中的方式是否有任何区别。例如。原始类型(int、byte 等)的变量在传递到方法时需要复制,以防止任何修改渗入调用代码,而如果参数标记为 final,则它可以“通过参考”没有这些顾虑,即不需要复制操作。

但是让我们把这个问题比这个例子更笼统:

是否存在在方法参数中添加final 会更改生成的字节码的情况?

【问题讨论】:

  • 最好使用final 方法参数专门用于public 方法以避免对传递的对象进行任何修改。
  • 也可以用于constant folding。原语不涉及引用,因此传递的值始终是“副本”。
  • @Braj final 适用于引用,而不是它所引用的对象。参数上的final 只会阻止您更改参数指向的内容。它不保护引用的对象。
  • 提示:从 Java 8 开始,如果在内部类中使用变量,则不再需要 final。编译器能够知道参数实际上是最终的。 JIT 比编译器更聪明。如果将 final 添加到参数对性能有任何影响,我会感到非常惊讶。

标签: java parameters bytecode final


【解决方案1】:

不,没有。这纯粹是编译时检查。

请注意,字节码的级别比您想象的要高 - 特别是没有原始内存地址。所有参数传递都被抽象掉了。此外,Java 编译器几乎没有优化。 JIT 负责在运行时进行所有优化。

此外,在实际的机器代码级别,通过引用传递单个单词参数可能不会优化任何东西。在正常情况下,复制它会更快(因为它无论如何都在寄存器中)。但同样,这是 JIT 担心的所有低级实现细节,而不是字节码的权限。

【讨论】:

  • 有道理。你知道在 JLS 的某个地方是否有这方面的参考吗?
  • @Markus JLS 很少谈论字节码。也许您正在考虑 JVMS。无论如何,这个问题并没有具体解决,但是看到在字节码级别没有最终的局部变量或参数(几乎没有任何局部变量的概念),很难相信它会产生不同之处。如果您想 100% 确定,则必须阅读编译器源代码。
  • 从 Java 8 开始,方法参数的 final 修饰符保留在 MethodParameters attribute 中,在运行时通过 Parameter.getModifiers() 可用。当然,最终参数仍然不会改变方法字节码。
  • @Jeffrey 感谢您提供信息。我还没有时间详细了解 Java 8 规范。
猜你喜欢
  • 2013-02-25
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 2019-03-08
  • 2014-10-09
  • 1970-01-01
  • 2012-05-14
  • 2018-02-20
相关资源
最近更新 更多