Java初始化順序

weixin_34239169發表於2018-01-11

Java初始化的順序如下:

[靜態變數, 靜態初始化塊] > [變數, 變數初始化塊] > 構造方法

靜態變數靜態初始化塊之間沒有先後關係, 遵循程式碼的先後順序, 寫在前面就先初始化, 所以如果你想要在靜態初始化塊裡引用在之後宣告的一個靜態變數, 會收到一個Compile Error.

public class InitialOrder {

    public static final void main(String[] args) {
        System.out.println("test: " + Test.STATIC_VARIABLE); //flag1
        //Test test = new Test();                            //flag2
    }
}

class Test {
    static String STATIC_VARIABLE = "static_variable";

    static {
        System.out.println(STATIC_VARIABLE);
        System.out.println("static_code_block");
    }

    static {
        System.out.println("another_code_block");
    }

    private String memberVariable = "member_variable";

    {
        System.out.println(memberVariable);
        System.out.println("code_block");
    }

    Test() {
        System.out.println("construction method");
    }
}

輸出:

static_variable
static_code_block
another_code_block
test: static_variable

可以看到, 當一個類的靜態變數被引用時, 所有的靜態變數以及靜態初始化塊都將被初始化. 這時候, 由於還沒有例項化物件, 故非靜態的初始化都不會進行.

如果我們註釋掉flag1處程式碼, 恢復flag2處程式碼, 執行結果如下:

static_variable
static_code_block
another_code_block
member_variable
code_block
construction method

當一個類例項化時, 靜態和非靜態的初始化都將進行. 同樣, 非靜態的初始化同樣有要求先後順序, 即一個變數初始化塊不能引用在之後宣告的一個變數, Illegal forward reference.

帶繼承關係的初始化順序
public class InitialOrderWithInherit {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

class Father {
    static String STATIC_VARIABLE = "father_static_variable";

    static {
        System.out.println(STATIC_VARIABLE);
        System.out.println("father_static_code_block");
    }

    private String memberVariable = "father_member_variable";

    {
        System.out.println(memberVariable);
        System.out.println("father_code_block");
    }

    Father() {
        System.out.println("father_construction");
    }

}

class Child extends Father {
    static String STATIC_VARIABLE = "child_static_variable";

    static {
        System.out.println(STATIC_VARIABLE);
        System.out.println("child_static_code_block");
    }

    private String memberVariable = "child_member_variable";

    {
        System.out.println(memberVariable);
        System.out.println("child_code_block");
    }

    Child() {
        System.out.println("child_construction");
    }

}

輸出:

father_static_variable
father_static_code_block
child_static_variable
child_static_code_block
father_member_variable
father_code_block
father_construction
child_member_variable
child_code_block
child_construction

若僅僅是引用了Child.STATIC_VARIABLE, 輸出如下:

father_static_variable
father_static_code_block
child_static_variable
child_static_code_block
child_static_variable

所以我們可以總結出如下順序:

父類--靜態變數
父類--靜態初始化塊
子類--靜態變數
子類--靜態初始化塊
父類--變數
父類--初始化塊
父類--構造器
子類--變數
子類--初始化塊
子類--構造器

相關文章