final
単純に、参照/プリミティブ変数に新しい値を割り当てることができないことを意味します。const
これは概念 (Java にはありません)と同じではありません。不変性を保証するものではありません。String
もちろん、Java ではすでに十分に不変です (厄介なリフレクション攻撃を除けば)。
パラメーター引数に修飾子を使用しfinal
ても、セキュリティやガベージ コレクションには影響しません。これは、読みやすさと、パラメーター変数がメソッド内で他の値を格納するために再利用されないというコーディング規則を強制するために行われます。
修飾子に遭遇するfinal
と、人間の読者は、一度割り当てられたこの変数の値がそのスコープ内で変更されないことを保証できます。コンパイラはこの動作を強制し、宣言された変数に新しい値を不正に代入しようとするプログラムをコンパイルしませんfinal
。
変数を宣言できますfinal
。final
変数は 1 回だけ割り当てることができます。final
割り当ての直前に割り当てが確実に解除されていない限り、変数が割り当てられると、コンパイル時エラーになります。
ただし、前述のように、final
それ自体は、参照されているオブジェクトの不変性を保証するものではありません。宣言は、 が一度割り当てられ、そのスコープ内にあると、別のインスタンスを参照しないことを保証しますfinal StringBuilder sb
。もちろん、それ自体は変更可能なオブジェクトです。sb
StringBuilder
StringBuilder
final
と内部クラス
モディファイアのもう 1 つの用途はfinal
、ローカル変数などを内部クラスで使用できるようにすることです。
使用されているが内部クラスで宣言されていないローカル変数、正式なメソッド パラメーター、または例外ハンドラー パラメーターは、宣言する必要がありますfinal
。
これは、これらの変数を使用する内部クラスが Java でコンパイルされる方法に関係しています。実装の詳細は、おそらく議論にはあまり関係ありません。基本的に、これらのfinal
変数の値は構築時に内部クラスに与えられます。ローカル変数へのその後の変更 (許可されている場合) は、内部クラスのインスタンスには表示されません。したがって、適切なセマンティクスを保証するために、これらのローカル変数を宣言する必要がありますfinal
。
final
実行時のローカル変数に対する修飾子の影響
final
final
ローカル変数/正式なメソッド パラメーターの修飾子はコンパイル時の概念であり、たとえばバイトコード レベルでは存在しません (つまり、フィールド、クラス、およびメソッドの修飾子とは非常に異なる役割を果たします)。したがって、この概念は、final
と 非final
ローカル変数が区別できない実行時には存在しません。キーワード自体を使用しても、ガベージ コレクションの可能性やパフォーマンスに影響はありません。
ガベージ コレクション可能性は、オブジェクトへのライブ参照があるかどうかという観点から定義されます。ローカル変数とメソッド引数は、宣言されているかどうかに関係なく、メソッド (またはそれらが宣言されているブロック) の最後でスコープ外になりますfinal
。範囲外に出るということは、参照が「死んでいる」ことを意味します。オブジェクト自体は、他の場所からのライブ参照をまだ持っている可能性があります。
この特定のケースではfinal
、内部クラスで使用できるように、正式なメソッド パラメーターが宣言されています。前述のように、内部クラスはこれらの参照を独自に使用するためにコピーします。したがって、この特定のケースでは、Authenticator
オブジェクトは および によって参照されるオブジェクトString
への参照を持ちます。a
b
簡単に言えば、オブジェクトへの参照が多ければ多いほど、コレクションの判読不能なガベージとして認定するのが難しくなります。ただし、根本的な要因は、これらの参照が有効かどうかではなく、これらの参照の有効性ですfinal
。
プロファイリングについて
メモリ使用量/パフォーマンスの問題に関する疑問を解決するために、概念を理解することをお勧めします。プロファイリングして問題が本物かどうかを確認し、必要に応じて修正することをお勧めします。適切に設計されたシステムは、この種の変更に高度に適応できる必要があります。