web-dev-qa-db-ja.com

Javaでローカル変数とメソッドパラメータを「最終」としてマークするのはなぜですか?

Javaでは、ローカルキーワードとメソッドパラメーターをfinalキーワードで修飾できます。

public static void foo(final int x) {
  final String qwerty = "bar"; 
}

そうすると、メソッドの本体でxとqwertyを再割り当てできなくなります。

これにより、一般的にプラスと見なされる不変性の方向にコードを微調整します。しかし、それはまた、どこにでも「最終」が現れるコードを乱雑にする傾向があります。 Javaのローカル変数とメソッドパラメーターの最終的なキーワードについてはどう思いますか?

57
Julien Chastang

適切な場合はいつでも、これを行うようにしてください。 「誤って」値を変更しようとしたときに警告するだけでなく、コンパイラに情報を提供するため、クラスファイルの最適化が向上します。これは、Robert Simmons、Jr.著の本「Hardcore Java」のポイントの1つです。実際、この本は、最適化を促進し、論理エラーを防ぐためのfinalの使用について、第2章をすべて使います。 PMDやEclipseのビルトインSAなどの静的分析ツールは、このような理由でこの種のケースにフラグを立てます。

53
rjray

私の個人的な意見は、それは時間の無駄だということです。視覚的な混乱と追加された冗長性は価値がないと思います。

エラーのある変数を再割り当てした(これはオブジェクトを不変にしない、つまり変数への別の参照を再割り当てできないことを意味する)ことは一度もありません。

しかし、もちろん、それはすべて個人的な好みです;-)

27
SCdF

パラメーターをfinalにするguaranteesメソッド内の任意の場所で使用される値は、渡された値を参照します。それ以外の場合は、特定の場所の上のすべてのコードを精神的に解析して、その時点でパラメーターが持つ値を知る必要があります。

したがって、not finalを使用すると、コードの可読性と保守性がすべて低下します。

最終的なローカル変数は意図に依存し、私の観点ではそれほど重要ではありません。何が起こるかに依存します。

ローカル変数の場合、これを避ける傾向があります。それは視覚的な混乱を引き起こし、通常は不要です。関数は、短くするか、単一のインパクトに焦点を合わせて、あなたがすべきでないものを変更していることをすぐに確認できるようにする必要があります。

マジックナンバーの場合は、コードではなく、とにかく定数プライベートフィールドとして配置します。

Finalは、必要な場合にのみ使用します(例:値を匿名クラスに渡す)。

6
Uri

Javaの " pass by reference "の動作は(ときどき)混乱する性質があるため、パラメータvarのファイナライズに間違いなく同意します。

ローカル変数のファイナライズは、IMOをやややり過ぎのようです。

5
javamonkey79

はい、できます。

それは読みやすさについてです。変数が一度だけ割り当てられることがわかっている場合、プログラムの可能な状態について推論するのは簡単です。

適切な代替策は、パラメーターが割り当てられたとき、または変数(ループ変数以外)が複数回割り当てられたときにIDE警告をオンにすることです。

3
Craig P. Motlin

少し混乱しますが、finalを置く価値があります。たとえば、Eclipseは、finalを自動的に配置できます。

2
fastcodejava

ローカル変数とメソッドパラメーターの作成finalは、これらのパラメーターを匿名クラスに渡したい場合-匿名スレッドをインスタンス化し、run()メソッドの本体でそれらのパラメーターにアクセスしたい場合に不可欠です。

それとは別に、コンパイラの最適化によりパフォーマンスが向上するかどうかはわかりません。最適化するかどうかは、特定のコンパイラの実装次第です...

finalを使用することで得られるパフォーマンス統計を知っておくとよいでしょう...

2
kartheek

finalには3つの理由があります。

  • コンストラクターによって設定されたインスタンス変数は不変になります
  • オーバーライドされないメソッドは最終的になります。デフォルトではなく、実際の理由でこれを使用してください
  • メソッド内の匿名クラスで使用されるローカル変数またはパラメーターは、finalである必要があります

メソッドと同様に、ローカル変数とパラメーターはfinalとして宣言する必要はありません。他の人が以前に言ったように、これはコンパイラのパフォーマンスの最適化のためのごくわずかな労力でコードを読みにくくします。これはほとんどのコードフラグメントの本当の理由ではありません。

2
Arne Burmeister

匿名クラスで使用されている場合は、Eclipseに任せます。これは、Google Collection APIの使用により増加しています。

0

ローカル変数については、それらが再割り当てされない、または再割り当てされるべきではないと考える場合、ここで行います。

パラメーターの再割り当てをチェックするCheckstyle-Checkがあるため、パラメーターは最終的なものではありません。もちろん、誰もパラメーター変数を再割り当てしたくないでしょう。

0
boutta

なぜしたいのですか?メソッドを作成したので、それを変更する人は常にqwertyから最終キーワードを削除して再割り当てできます。メソッドのシグニチャーについては、同じ推論で、クラスのサブクラスに対して何が行われるのかわかりませんが...最終パラメーターを継承する可能性があり、メソッドをオーバーライドしたとしても、xを最終化できません。それを試して、それが機能するかどうかを調べてください。

したがって、唯一の本当の利点は、パラメーターを不変にし、子に引き継ぐ場合です。それ以外の場合は、特に正当な理由がないためにコードが乱雑になります。誰もあなたのルールに従うことを強制しない場合は、最後の修飾子を与えるのではなく、そのパラメーターまたは変数を変更してはならない理由として、良いコメントを残しておく方が良いでしょう。

編集

コメントへの回答として、パフォーマンスの問題が発生している場合、ローカル変数とパラメーターを最終的にすることで、コンパイラーがコードをより最適化できるようにすることができます。ただし、コードの不変性の観点から、私は元のステートメントを支持します。

0
Elie