【问题标题】:Is there any performance reason to declare method parameters final in Java?在 Java 中声明方法参数 final 是否有任何性能原因?
【发布时间】:2010-09-20 23:25:18
【问题描述】:

在 Java 中声明方法参数 final 是否有任何性能原因?

如:

public void foo(int bar) { ... }

对比:

public void foo(final int bar) { ... }

假设bar 仅在foo() 中被读取而从未被修改。

【问题讨论】:

  • 我想不出编译器会关心您是否声明方法参数 final 的原因。但这个问题的真正答案是——写两个函数,一个带有最终参数,一个带有常规参数。每次运行它们一百万次,看看是否有任何明显的运行时差异。如果您担心性能,那么对您的代码进行一些分析工作并找出究竟是什么让您慢下来是非常重要的。这几乎肯定不是你所期望的:)
  • 我建议你永远不要编写微基准测试。您不知道 JIT 可以进行哪些优化以及何时进行,并且您可能会错误地理解它仅在执行“简单测试用例”时的行为方式
  • 可能是这样,但这里没有人写过或建议过微基准测试...
  • @Mike Blandford 的回答建议使用微基准,不是吗?
  • 用 Java 编写微基准测试非常棘手

标签: java performance final


【解决方案1】:

除了在方法中声明的非最终局部变量之外,还有一点——内部类实例可能比堆栈帧更长寿,因此局部变量可能会在内部对象仍然存在时消失

【讨论】:

    【解决方案2】:

    final 关键字不会出现在局部变量和参数的类文件中,因此它不会影响运行时性能。它的唯一用途是澄清编码人员不更改变量的意图(许多人认为其使用的可疑原因),并处理匿名内部类。

    关于方法本身的 final 修饰符是否有任何性能提升存在很多争论,因为无论如何,无论修饰符如何,优化编译器都会在运行时内联方法。在这种情况下,它也应该只用于限制方法的覆盖。

    【讨论】:

    • 您可能认为 final 变量/参数可以优化为循环变量......但是一个好的编译器/运行时应该能够在没有 final 的情况下解决这个问题......
    • 当这两种方法之间的唯一区别是局部变量的“最终性”时,我已经看到 Sun 的编译器发出的字节码略短。微优化是真实存在的,编译器确实做到了。当然,真正重要的是 JIT 对字节码的处理方式,而本地引用在编译为字节码时会失去其“最终性”。我认为这就是为什么对最终局部变量有这么多猜测的原因:结果是什么是非常不确定的。然而,使用 final locals 会影响字节码——不管它的价值是什么。
    • 由于它是非确定性的,因此也没有任何方法可以依赖优化。当然,自 2008 年的原始答案以来,VM 实现可能发生了很多变化;-)
    【解决方案3】:

    我假设编译器可能会删除所有具有原始类型(例如 int)的私有静态最终变量,并将它们直接内联到代码中,就像使用 C++ 宏一样。

    但是,我不知道这是否在实践中完成,但可以这样做以节省一些内存。

    【讨论】:

    • 问题不在于私有 statc 最终变量。
    【解决方案4】:

    final 参数的唯一好处是它可以在匿名嵌套类中使用。如果一个参数从不改变,即使没有 final 修饰符,编译器也会将其检测为正常操作的一部分。错误是由意外分配的参数引起的非常罕见 - 如果您的方法大到需要这种级别的工程,请将它们缩小 - 您调用的方法不能更改您的参数。

    【讨论】:

    • “错误是由意外分配的参数引起的”。它比你想象的更常见......
    • @RAY 你可能是对的,实际上我没有任何数据(根据我自己的经验)来支持这种说法。
    • @DobesVandermeer 更准确地说,这并不是真正的“最终参数的好处”。您所描述的只是任何局部变量(我将参数包括在内)的必需语法,以使其对匿名嵌套类的局部范围可见。
    【解决方案5】:

    在类加载后运行的编译器(例如 JIT 编译器)可以利用 final 方法。因此,声明为 final 的方法可能具有一些性能优势。

    http://www.javaperformancetuning.com/tips/final.shtml

    还有一个好资源

    http://mindprod.com/jgloss/final.html

    【讨论】:

    • 问题是关于参数被声明为最终的,这对性能没有影响。
    • 在现代 JIT'S (Hotspot) final 上根本没有任何(可测量的)性能影响,无论是应用于参数还是类
    • 您链接的两篇文章都表明 final 对开发人员来说是一个语义标记,并且 JIT 编译器可能使用 final (但正如其他人指出的那样,他们并不真正需要该信息) .所以 final 是相当语义化的,这与现代 C/++ 编译器能够推断变量和方法的 const 性(即使它们没有显式标记为 const )是平行的。
    猜你喜欢
    • 2015-11-01
    • 2015-07-28
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 2019-03-08
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多