Java 靜態語句塊 語句塊 構造方法的調用順序

最近對 ‘Java 靜態語句塊 語句塊 構造方法的調用順序’ 這個問題有點模糊,跑了段代碼用來幫助理解。代碼如下

父類

public class Parent {

    static {
        System.out.println("parent static block");
    }

    {
        System.out.println("parent block");
    }

    public Parent() {
        System.out.println("parent constract");
    }

}

子類

public class Child extends Parent {

    static {
        System.out.println("child static block");
    }

    {
        System.out.println("child block");
    }

    public Child() {
        System.out.println("child constract");
    }

    public static void main( String[] args ) {
        new Child();
    }

}

最後運行的結果如下

parent static block
child static block
parent block
parent constract
child block
child constract

總結如下:
父類的靜態代碼塊最先執行,然後是執行子類的靜態代碼塊。
然後是父類的代碼塊和父類的構造方法依次執行。
接着是子類的代碼塊和子類的構造方法依次執行。

靜態代碼塊只執行一次,非靜態代碼塊在 new 的時候都會執行一次。

爲什麼會是這樣的結果呢?如果要知道原因的話,我們需要知道 JVM 在加載 class 字節碼的相關知識。

類在 JVM 裏面總共經歷了 7 個過程,分別是 加載、驗證、準備、解析、初始化、使用和卸載。

加載的過程就是從文件、網絡或二進制流裏面把類加載到內存,並轉化爲方法區運行時結構。

驗證的過程就是驗證魔數、版本號等是否符合 JVM 要求。

準備的過程就是給類的靜態屬性分類空間並賦初始值,需要注意的是引用的初始值爲 null ,其他基礎類型均爲 0 ,如果是常量(static final) 那麼就賦值爲 = 號後面的值或表達式的值。

解析和初始化階段,這 2 個階段沒有明確的區分,這個時候就是給靜態變量賦值,同時執行靜態代碼塊。按照代碼的順序依次執行。

使用和卸載就不詳細說了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章