2

StringJava プログラムでは、メソッド宣言のように定義されるパラメーター。ただし、メソッド定義では、final String変数としてアクセスされます。いくつかの問題(セキュリティ、メモリの問題など)につながるかどうか?

例えば:

メソッド宣言

join(String a,String b);

メソッド定義

public void join(final String a,final String b)
{
    Authenticator au = new Authenticator(){
        public PasswordAuthentication getPasswordAuthentication(){
        return new PasswordAuthentication(a,b)}
    };
}

私を助けて、私の疑問を明確にしてください。前もって感謝します

PS私は内部クラスで使用する必要があるため、最終変数としてaとbにアクセスしています。

4

4 に答える 4

18

final単純に、参照/プリミティブ変数に新しい値を割り当てることができないことを意味します。constこれは概念 (Java にはありません)と同じではありません。不変性を保証するものではありません。Stringもちろん、Java ではすでに十分に不変です (厄介なリフレクション攻撃を除けば)。

パラメーター引数に修飾子を使用しfinalても、セキュリティやガベージ コレクションには影響しません。これは、読みやすさと、パラメーター変数がメソッド内で他の値を格納するために再利用されないというコーディング規則を強制するために行われます。

修飾子に遭遇するfinalと、人間の読者は、一度割り当てられたこの変数の値がそのスコープ内で変更されないことを保証できます。コンパイラはこの動作を強制し、宣言された変数に新しい値を不正に代入しようとするプログラムをコンパイルしませんfinal

JLS 14.2.4final変数

変数を宣言できますfinalfinal変数は 1 回だけ割り当てることができます。final割り当ての直前に割り当てが確実に解除されていない限り、変数が割り当てられると、コンパイル時エラーになります。

ただし、前述のように、finalそれ自体は、参照されているオブジェクトの不変性を保証するものではありません。宣言は、 が一度割り当てられ、そのスコープ内にあると、別のインスタンスを参照しないことを保証しますfinal StringBuilder sb。もちろん、それ自体は変更可能なオブジェクトです。sbStringBuilderStringBuilder


finalと内部クラス

モディファイアのもう 1 つの用途はfinal、ローカル変数などを内部クラスで使用できるようにすることです。

JLS 8.1.3 内部クラスとそれを囲むインスタンス

使用されているが内部クラスで宣言されていないローカル変数、正式なメソッド パラメーター、または例外ハンドラー パラメーターは、宣言する必要がありますfinal

これは、これらの変数を使用する内部クラスが Java でコンパイルされる方法に関係しています。実装の詳細は、おそらく議論にはあまり関係ありません。基本的に、これらのfinal変数の値は構築時に内部クラスに与えられます。ローカル変数へのその後の変更 (許可されている場合) は、内部クラスのインスタンスには表示されません。したがって、適切なセマンティクスを保証するために、これらのローカル変数を宣言する必要がありますfinal


final実行時のローカル変数に対する修飾子の影響

finalfinalローカル変数/正式なメソッド パラメーターの修飾子はコンパイル時の概念であり、たとえばバイトコード レベルでは存在しません (つまり、フィールド、クラス、およびメソッドの修飾子とは非常に異なる役割を果たします)。したがって、この概念は、finalと 非finalローカル変数が区別できない実行時には存在しません。キーワード自体を使用しても、ガベージ コレクションの可能性やパフォーマンスに影響はありません。

ガベージ コレクション可能性は、オブジェクトへのライブ参照があるかどうかという観点から定義されます。ローカル変数とメソッド引数は、宣言されているかどうかに関係なく、メソッド (またはそれらが宣言されているブロック) の最後でスコープ外になりますfinal。範囲外に出るということは、参照が「死んでいる」ことを意味します。オブジェクト自体は、他の場所からのライブ参照をまだ持っている可能性があります。

この特定のケースではfinal、内部クラスで使用できるように、正式なメソッド パラメーターが宣言されています。前述のように、内部クラスはこれらの参照を独自に使用するためにコピーします。したがって、この特定のケースでは、Authenticatorオブジェクトは および によって参照されるオブジェクトStringへの参照を持ちます。ab

簡単に言えば、オブジェクトへの参照が多ければ多いほど、コレクションの判読不能なガベージとして認定するのが難しくなります。ただし、根本的な要因は、これらの参照が有効かどうかではなく、これらの参照の有効性ですfinal


プロファイリングについて

メモリ使用量/パフォーマンスの問題に関する疑問を解決するために、概念を理解することをお勧めします。プロファイリングして問題が本物かどうかを確認し、必要に応じて修正することをお勧めします。適切に設計されたシステムは、この種の変更に高度に適応できる必要があります。

于 2010-06-10T10:34:36.547 に答える
3

いいえ、引数のfinalオンは、メソッドのスタック フレーム上の引数のローカル コピーにのみ影響します。引数として渡される値に影響を与えたり、変更したりすることはありません。

于 2010-06-10T10:34:36.673 に答える
0

追加finalしても署名が変更されたり、その他の問題が発生したりすることはありません。したがって、インターフェイスで指定されたメソッドで使用しても問題ありません (たとえば)。メソッド内のコードにのみ違いがあります。

于 2010-06-10T10:35:05.397 に答える
0

変数の作成はfinal、セキュリティやメモリ割り当てとは関係ありません。セキュリティやメモリの使用には影響しません。

于 2010-06-10T10:35:10.713 に答える