Javaでメソッドパラメータをfinalと宣言するパフォーマンス上の理由はありますか?


117

Javaでメソッドパラメータをfinalと宣言するパフォーマンス上の理由はありますか?

のように:

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

対:

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

それbarが読み込まれるだけで、で変更されないと仮定しfoo()ます。


メソッドパラメータをfinalと宣言したかどうかをコンパイラが気にする理由は考えられません。しかし、この質問に対する本当の答えは、2つの関数を記述します。1つは最終パラメーターを使用し、もう1つは通常パラメーターを使用します。それらをそれぞれ100万回実行し、顕著なランタイムの違いがあるかどうかを確認します。パフォーマンスが心配な場合は、コードのプロファイリング作業を行い、何が原因でパフォーマンスが低下しているかを正確に把握することが非常に重要です。それはあなたがそれがそうであるとあなたが期待するであろうことはほとんど確かではない:)
マイク・ブランドフォード'05年

1
マイクロベンチマークを記述しないでください。JITがどの最適化をいつ実行できるかわからないため、「単純なテストケース」を実行するだけで、JITがどのように動作するかについて誤った考えを得る可能性があります
Edmondo1984

まあそれはそうかもしれませんが、ここでは誰もマイクロベンチマークを書いたり提案したりしていません...
Kip

1
@マイク・ブランドフォードの答えは、マイクロベンチマークを使用しないことを示唆していますか?
ベンページ

Javaでマイクロベンチマークを書くことは非常にトリッキーなことです
Edmondo1984

回答:


97

最後のキーワードは、ローカル変数とパラメーターのクラスファイルには表示されないため、実行時のパフォーマンスに影響を与えることはありません。これは、変数が変更されない(多くの場合、その使用には疑わしい理由を考慮している)ことを意図し、匿名の内部クラスを扱うことを明確にするためにのみ使用されます。

メソッドは修飾子に関係なく、実行時に最適化コンパイラによってインライン化されるため、メソッド自体のfinal修飾子にパフォーマンスの向上があるかどうかについては、多くの議論があります。この場合も、メソッドのオーバーライドを制限するためにのみ使用する必要があります。


5
良いコンパイラ/ランタイムがその最終とにかくせずに出て...フィギュアにできるはずであるのに...しかし、あなたはその最後の変数は/ paramsをループ変数として最適化することができると思いたい
ジョン・ガードナー

9
2つのメソッドの唯一の違いがローカル変数の「ファイナリティ」である場合、Sunのコンパイラがわずかに短いバイトコードを出力するのを見ました。マイクロ最適化は現実のものであり、コンパイラーは実際に最適化を行います。もちろん、本当に重要なのは、JITがバイトコードをどのように処理するかであり、ローカル参照は、バイトコードにコンパイルされると「ファイナリティ」を失います。これが、最終的なローカル変数について非常に多くの推測がある理由だと思います。結果がどうなるかは非常に非決定的です。ただし、最終的なローカルを使用すると、バイトコードに影響を与える可能性があります。
Christopher Schultz

非決定的であるため、最適化に依存する方法もありません。もちろん、2008年の最初の回答以来、VMの実装には多くの変更があった可能性があります;-)
Robin

15

finalパラメータの唯一の利点は、匿名のネストされたクラスで使用できることです。パラメーターが変更されない場合、コンパイラーはfinal修飾子がなくても、それを通常の操作の一部として既に検出します。パラメータが予期せず割り当てられることによってバグが発生することは非常にまれです-メソッドがこのレベルのエンジニアリングを必要とするほど大きい場合、それらを小さくします-呼び出すメソッドはパラメータを変更できません。


8
「パラメータが予期せず割り当てられることによってバグが発生することは非常にまれです」。それはあなたが思うよりも一般的です...
RAY

2
@RAYあなたは正しいかもしれませんが、実際には私はその主張を裏付けるデータを(自分の経験以外に)持っていません。
Dobes Vandermeer

@DobesVandermeerをより正確に言うと、これは実際には「最終パラメータの利点」ではありません。あなたが説明しているのは、匿名変数のネストされたクラスのローカルスコープから見えるようにするために、ローカル変数(パラメーターを含む)に必要な構文です。
スウビー2017年

0

JITコンパイラなど、クラスのロード後に動作するコンパイラは、finalメソッドを利用できます。その結果、finalと宣言されたメソッドには、パフォーマンス上の利点があります。

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

ああ、別の良いリソース

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


10
問題は、パフォーマンスに影響を与えない、最終的に宣言されているパラメーターについてでした。
ロビン

近代的なJITで最終'S(ホットスポット)は、パラメータまたはクラスに適用されるかどうか、まったく(測定可能)パフォーマンスの影響を持っていません
kohlerm

2
両方をリンクする2つの記事は、finalが開発者にとって意味論的なマークであり、JITコンパイラーがfinalを使用する可能性があることを示唆しています(ただし、他の人が指摘したように、実際にはその情報は必要ありません)。したがって、finalはかなりセマンティックです。これは、変数やメソッドのconstnessが明示的にconstとしてマークされていなくても、それらを推定する最新のC / ++コンパイラの機能と並行しています。
ron

0

メソッド内で宣言された最終ではないローカル変数を使用することに加えて、内部クラスインスタンスがスタックフレームよりも長く存続する可能性があるため、内部オブジェクトがまだ生きている間にローカル変数が消える可能性があります


-2

コンパイラーは、intなどのプリミティブ型を持つすべてのプライベート静的final変数を削除し、C ++マクロと同じようにコードに直接インライン化できる可能性があると思います。

しかし、これが実際に行われるかどうかはわかりませんが、メモリを節約するために行うことができます。


問題は、プライベートstatc最終変数についてではありません。
ローン侯爵
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.