23

初期化が発生する順序、または初期化がこの順序で発生する理由を発見しようとしています。コードを考えると:

public class Main {

    {
        System.out.printf("NON-STATIC BLOCK\n");
    }

    static{
        System.out.printf("STATIC BLOCK\n");
    }

    public static Main m = new Main();

    public Main(){
        System.out.printf("MAIN CONSTRUCTOR\n");
    }

    public static void main(String... args) {
        //Main m = new Main();
        System.out.printf("MAIN METHOD\n");

    }
}

出力:

STATIC BLOCK

NON-STATIC BLOCK

MAIN CONSTRUCTOR

MAIN METHOD

ただし、m初期化ブロックの前に の宣言を移動すると、次のようになります。

NON-STATIC BLOCK

MAIN CONSTRUCTOR

STATIC BLOCK

MAIN METHOD

なぜこの順序で発生するのか、私にはまったくわかりません。staticさらに、の宣言でキーワードを削除するとm、init ブロックもコンストラクターも起動しません。誰でもこれで私を助けることができますか?

4

1 に答える 1

28

JLS のセクション 12.4.2 が欠落しているだけだと思います。これには次が含まれます。

次に、クラスのクラス変数初期化子と静的初期化子、またはインターフェイスのフィールド初期化子のいずれかを、単一のブロックであるかのように、テキストの順序で実行します。

「テキスト順」の部分が重要です。

m静的変数からインスタンス変数に変更すると、フィールドはクラスの初期化によって初期化されません。インスタンスの初期化によってのみ初期化されます(つまり、インスタンスが構築されるとき)。現時点では、スタック オーバーフローが発生します。1 つのインスタンスを作成するには、別のインスタンスを作成する必要があり、別のインスタンスを作成する必要があります。

編集: 同様に、セクション 12.5では、次の手順を含むインスタンスの初期化を指定しています。

  • このクラスのインスタンス初期化子とインスタンス変数初期化子を実行し、インスタンス変数初期化子の値を対応するインスタンス変数に割り当てます。この順序は、クラスのソース コードにテキストで表示される左から右の順序です。これらの初期化子のいずれかを実行すると例外が発生した場合、それ以上の初期化子は処理されず、このプロシージャは同じ例外で突然終了します。それ以外の場合は、ステップ 5 に進みます。

  • このコンストラクターの残りの本体を実行します。その実行が突然完了した場合、このプロシージャは同じ理由で突然完了します。それ以外の場合、この手順は正常に完了します。

そのため、「MAIN CONSTRUCTOR」の前に「NON-STATIC BLOCK」が表示されています。

于 2013-09-27T19:39:42.047 に答える