質問

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

どうしてクラスのyトラフを使用することを許可されますか?

Yはいつ定義されますか?

役に立ちましたか?

解決

クラス変数へのフォワードリファレンスを管理する正確なルールについては、セクションで説明します §8.3.2.3 JLS:

8.3.2.3初期化中のフィールドの使用に関する制限

メンバーの宣言は、メンバーがそれぞれインスタンスである場合にのみ使用する前にテキストを表示する必要があります static)クラスまたはインターフェイスCのフィールドおよび次のすべての条件は次のとおりです。

  • 使用は、それぞれ(それぞれ(それぞれ)発生します(それぞれ) static)cまたはインスタンスの変数初期イザー(それぞれ) static)Cのイニシャルイザー
  • 使用法は、割り当ての左側にありません。
  • 使用法は単純な名前を介して行われます。
  • Cは、使用法を囲む最も内側のクラスまたはインターフェイスです。

上記の4つの要件のいずれかが満たされていない場合、コンパイル時間エラーが発生します。

これは、コンパイル時間エラーがテストプログラムから生じることを意味します。

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }

一方、次の例はエラーなしでコンパイルされます。

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }

コンストラクターであっても (§8.8) テストの場合、3行後に宣言されるフィールドKを指します。

これらの制限は、コンパイル時に、円形またはその他の奇形の初期化をキャッチするように設計されています。したがって、両方:

class Z {
  static int i = j + 2; 
  static int j = 4;
}

と:

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}

コンパイル時間エラーが発生します。メソッドによるアクセスはこの方法でチェックされていないので、:

class Z {
  static int peek() { return j; }
  static int i = peek();
  static int j = 1;
}
class Test {
  public static void main(String[] args) {
      System.out.println(Z.i);
  }
}

出力を生成します:

0

Iの変数初期化は、classメソッドPeekを使用して変数Jの値にアクセスするため、jが変数初期化によって初期化され、その時点でデフォルト値がまだあります。 (§4.12.5).

他のヒント

クラスを使用することにより、コンパイラはクラスが完了するまで変数を探すことができるので、yを見つけますが、コメントのように定義するだけではまだ定義されていないので失敗します。

静的変数は、クラスの読み込み中に、クラスの宣言の順に定義されます。 JVMがロードするとき Main クラス、 x 次に、定義されます y. 。そのため、直接使用できません y 初期化するとき x, 、aと呼ばれるものを作成します フォワードリファレンス, 、あなたは現在定義されていない変数を指し、それはコンパイラにとって違法です。

使用するとき Main.y, 、次のことが起こると思います:

  • ロードします Main, x 初期化が呼び出されます
  • 定義するとき x 等しい Main.y, 、コンパイラはクラスへの参照を見ているので、定義の定義が終了します x メンバーの現在の価値に y クラスの Main. 。このケースをまるで扱います Main 別のクラスでした。

この場合、初期化するときに注意してください x, y 今のところ定義されていません。それで x 値があります 0.

それは意味がないので、あなたはそれをすることを許可されていません。唯一の可能な解釈はそれです y ゼロに初期化されており、すでに2つの方法があります。あなたはこれを必要としません。

おそらく、コンパイラは、作成されたときにクラスのデフォルト値を持つ静的変数の参照を作成し、指定された値を割り当てます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top