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


117

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

如:

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

与:

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

假设bar只能在中读取而不进行修改foo()


我想不出为什么编译器会在意是否将方法参数声明为final的原因。但是,此问题的真正答案是-编写两个函数,一个具有最终参数,一个具有常规参数。每次运行它们一百万次,看看是否存在明显的运行时差异。如果您担心性能,对代码进行一些性能分析工作并找出导致速度下降的确切原因非常重要。几乎可以肯定,这不是您所期望的:)
Mike Blandford

1
我建议您不要写微观基准。您不知道JIT可以进行哪种优化以及何时进行优化,而您可能只是通过执行“简单测试用例”就
误解

可能是这样,但是这里没有人写过或建议过一个微基准测试
Kip

1
@Mike Blandford的答案表明使用微基准不是吗?
本·佩奇

用Java编写微基准测试非常棘手
Edmondo1984

Answers:


97

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

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


5
您可能会认为最终变量/参数可以作为循环变量进行优化...但是,一个好的编译器/运行时应该能够在没有最终变量的情况下弄清楚这一点……
John Gardner

9
我已经看到,当两种方法之间的唯一区别就是局部变量的“最终性”时,Sun的编译器会发出略短的字节码。微观优化是一件实事,而编译器确实可以做到。当然,真正重要的是JIT对字节码的处理方式,本地引用在编译为字节码时会丢失其“最终确定性”。我认为这就是为什么对最终局部变量的猜测如此之多:结果的确切性是不确定的。但是,使用final locals可能会影响字节码-就其价值而言。
Christopher Schultz

由于它不是确定性的,所以实际上也没有任何方法可以依靠优化。当然,自2008年最初的回答以来,VM的实现可能发生了很多变化;-)
罗宾(Robin)

15

final参数的唯一好处是可以在匿名嵌套类中使用它。如果从未更改过参数,则即使没有final修饰符,编译器也已将其检测为正常操作的一部分。错误很少是由意外分配的参数引起的-如果您的方法足够大,需要这种程度的工程设计,请减小它们的大小-您调用的方法无法更改参数。


8
“错误是由意外分配的参数引起的,这非常罕见”。它比您想像的还要普遍...
RAY

2
@RAY您可能是对的,实际上我没有任何数据(超出我的经验)来支持该声明。
Dobes Vandermeer '02

@DobesVandermeer更精确地说,这并不是“最终参数的好处”。您所描述的只是对任何使匿名嵌套类的本地作用域可见的局部变量(我将其中包括参数)所需的语法。
swooby

0

在类加载之后运行的编译器(例如JIT编译器)可以利用final方法。因此,声明为final的方法可能会带来一些性能上的好处。

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

哦,另一个好的资源

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


10
问题在于参数被声明为final,这对性能没有影响。
罗宾

在现代的JIT'S(热点)决赛中,无论是应用于参数还是类别,最终都根本没有任何(可衡量的)性能影响
kohlerm

2
您链接的两篇文章都建议final对开发人员而言是一个语义标记,并且JIT编译器可以使用final(但正如其他人指出的那样,他们实际上并不需要该信息)。因此final是相当语义的,这与现代C / ++编译器能够推断变量和方法的常量性(即使未明确标记为const)并行。
ron

0

还有一点需要说明的是,使用方法中声明的非最终局部变量,内部类实例的寿命可能超过堆栈框架,因此,当内部对象仍处于活动状态时,局部变量可能会消失


-2

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

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


问题不在于私有statc最终变量。
罗恩侯爵,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.