3

JLS 8.3.2.3を実行したとき、次のコードを理解できませんでした。

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

コードの結果、エラーが発生しますCannot reference a field before it is defined

しかし、コードを次のように変更すると

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

コードがコンパイルされています。ただし、どちらの場合も、変数定義は初期化ブロックの後にあります。この背後にある謎は何ですか?

4

3 に答える 3

8

宣言よりも前に値を割り当てることができます-それを読み取ることはできません。したがって、これも失敗します。

static { System.out.println(j + 2); }
static int j;

これは問題ありませんが:

static { j = 5; }
static int j;

セクション 8.3.2.3の無効な使用法の 4 つの条件の 1 つ:

  • 使用法は割り当ての左側にありません。

(そのセクションの二重否定は頭を痛めていますが、関連性があると思います!)

正直なところ、仕様のその部分は私が見た中で最悪のものの 1 つで、本当に不明確です。しかし、結果として、割り当てることはできますが、読み取ることはできません:)

于 2013-01-21T07:32:09.437 に答える
1

実際、それはコンパイラの基本であり、

割り当てステートメントは右から左に実行されます。

例えばi=2;

これは、2がiに割り当てられ、2が定数であるため、宣言する必要がないことを意味します。

一方、私たちが書く場合

i=j+2;

最初にjをコンパイルしてから、それをiに割り当てます。したがって、jがまだ定義されていないため、エラーが発生します。

于 2013-01-21T07:39:05.830 に答える
0

で、 別の静的ブロックで初期化されるi = j + 2;変数を使用します。j

コードをコンパイルするには、すべてを1つの静的ブロック、j初期化、および式にまとめる必要があります。このコードは機能します:

public class Z {

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

}

ダビデ

于 2013-01-21T07:38:17.917 に答える