コンストラクターが完了する前に最終変数を初期化する必要があるのはなぜですか?
public class Ex
{
final int q;
}
このコードをコンパイルすると、次のようなエラーが発生します
err:変数 q が初期化されていない可能性があります
コンストラクターが完了する前に最終変数を初期化する必要があるのはなぜですか?
public class Ex
{
final int q;
}
このコードをコンパイルすると、次のようなエラーが発生します
err:変数 q が初期化されていない可能性があります
正式な理由は、 Java 言語仕様 8.3.1.2で定義されているためです。
空白の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。そうしないと、コンパイル時エラーが発生します。
空白の final は、宣言に初期化子 (つまり、記述したもの) がない final 変数です。
変数を変更できないためfinal
ですが、ある時点で初期化する必要があり、コンストラクターはそうするのに適した場所です。
あなたの場合、宣言時に初期化されていないため、空白のファイナルと呼ばれます。
変数の値はfinal
一度しか設定できません。コンストラクターは、これが当てはまることを保証できるクラスのコード内の唯一の場所です。コンストラクターはオブジェクトに対して一度だけ呼び出されますが、他のメソッドは何度でも呼び出すことができます。
変数は、宣言時またはコンストラクターで初期化するfinal
必要があります。
コンストラクターが戻るときに初期化されていない場合、初期化されず、初期化されていない変数のままになる可能性があります。コンパイラは、それが初期化されることを証明できないため、エラーをスローします。
このウィキペディアの抜粋は、それをよく説明しています。
final 変数は、初期化子または代入ステートメントを介して 1 回だけ初期化できます。宣言の時点で初期化する必要はありません。これは「空白の最終」変数と呼ばれます。クラスの空の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。同様に、空白の final 静的変数は、それが宣言されているクラスの静的初期化子で確実に割り当てる必要があります。そうしないと、どちらの場合もコンパイル時エラーが発生します。(注: 変数が参照である場合、これは、変数を別のオブジェクトを参照するように再バインドできないことを意味します。ただし、参照するオブジェクトは、元々変更可能であった場合でも変更可能です。)
フィールドに適用されるfinal
キーワードには、次の 2 つの効果のいずれかがあります。
final HashMap<String,String> a
設定することはできませんが、 ,sを実行することを妨げるものは何もないということです。オブジェクトの内容。this.a=new HashMap<String,String>();
this.a.put("a","b")
final
修飾子は、変数の値を変更できないようにするため、宣言した場所で初期化する必要があります。
Final
修飾子では、変数の値を変更できません。したがって、ある場所で値を割り当てる必要があり、コンストラクターはこの場合にこれを行う必要がある場所です。
言語仕様には、最終的な変数とフィールドのプロパティに関する特定の保証が含まれており、そのうちの 1 つは、適切に構築されたオブジェクト (つまり、コンストラクターが正常に終了したオブジェクト) は、すべての最終インスタンス フィールドが初期化され、すべてのスレッドに表示される必要があることです。したがって、コンパイラはコード パスを分析し、それらのフィールドを初期化する必要があります。