45

コンストラクターが完了する前に最終変数を初期化する必要があるのはなぜですか?

public class Ex
{
  final int q;
}

このコードをコンパイルすると、次のようなエラーが発生します

err:変数 q が初期化されていない可能性があります

4

9 に答える 9

37

正式な理由は、 Java 言語仕様 8.3.1.2で定義されているためです。

空白の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。そうしないと、コンパイル時エラーが発生します。

空白の final は、宣言に初期化子 (つまり、記述したもの) がない final 変数です。

于 2012-07-05T13:26:34.977 に答える
15

変数を変更できないためfinalですが、ある時点で初期化する必要があり、コンストラクターはそうするのに適した場所です。

あなたの場合、宣言時に初期化されていないため、空白のファイナルと呼ばれます。

于 2012-07-05T13:14:21.510 に答える
14

変数の値はfinal一度しか設定できません。コンストラクターは、これが当てはまることを保証できるクラスのコード内の唯一の場所です。コンストラクターはオブジェクトに対して一度だけ呼び出されますが、他のメソッドは何度でも呼び出すことができます。

于 2012-07-05T13:16:25.580 に答える
11

変数は、宣言時またはコンストラクターで初期化するfinal必要があります。

コンストラクターが戻るときに初期化されていない場合、初期化されず、初期化されていない変数のままになる可能性があります。コンパイラは、それが初期化されることを証明できないため、エラーをスローします。

このウィキペディアの抜粋は、それをよく説明しています。

final 変数は、初期化子または代入ステートメントを介して 1 回だけ初期化できます。宣言の時点で初期化する必要はありません。これは「空白の最終」変数と呼ばれます。クラスの空の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。同様に、空白の final 静的変数は、それが宣言されているクラスの静的初期化子で確実に割り当てる必要があります。そうしないと、どちらの場合もコンパイル時エラーが発生します。(注: 変数が参照である場合、これは、変数を別のオブジェクトを参照するように再バインドできないことを意味します。ただし、参照するオブジェクトは、元々変更可能であった場合でも変更可能です。)

于 2012-07-05T13:20:21.810 に答える
6

フィールドに適用されるfinalキーワードには、次の 2 つの効果のいずれかがあります。

  • プリミティブでは、プリミティブの値が変更されるのを防ぎます (int は値を変更できません)。
  • オブジェクトでは、「変数の値」、つまりオブジェクトへの参照が変更されるのを防ぎます。つまり、 がある場合、一度しか設定できず、再度final HashMap<String,String> a設定することはできませんが ,sを実行することを妨げるものは何もないということです。オブジェクトの内容。this.a=new HashMap<String,String>();this.a.put("a","b")
于 2012-07-05T13:18:34.040 に答える
2

final修飾子は、変数の値を変更できないようにするため、宣言した場所で初期化する必要があります。

于 2012-07-05T13:14:00.343 に答える
0

Final修飾子では、変数の値を変更できません。したがって、ある場所で値を割り当てる必要があり、コンストラクターはこの場合にこれを行う必要がある場所です。

于 2012-07-05T13:14:51.263 に答える
0

言語仕様には、最終的な変数とフィールドのプロパティに関する特定の保証が含まれており、そのうちの 1 つは、適切に構築されたオブジェクト (つまり、コンストラクターが正常に終了したオブジェクト) は、すべての最終インスタンス フィールドが初期化され、すべてのスレッドに表示される必要があることです。したがって、コンパイラはコード パスを分析し、それらのフィールドを初期化する必要があります。

于 2012-07-05T13:15:46.527 に答える