Java父子類載入順序

lean.li發表於2018-10-15

載入順序

先上桌結論:

父類靜態屬性(成員變數) > 父類靜態程式碼塊 > 子類靜態屬性 > 子類靜態程式碼塊 > 父類非靜態屬性 > 父類非靜態程式碼塊 > 父類構造器 > 子類非靜態屬性 > 子類非靜態程式碼塊 > 子類構造器

這麼長怎麼記呀?!

這裡幫大家小結幾個特點:

  1. 靜態屬性和程式碼塊,當且僅當該類在程式中第一次被 new 或者第一次被類載入器呼叫時才會觸發(不考慮永久代的回收)。也正是因為上述原因,類優先於物件 載入/new,即 靜態優先於非靜態
  2. 屬性(成員變數)優先於構造方法,可以這麼理解,載入這整個類,需要先知道類具有哪些屬性,並且這些屬性初始化完畢之後,這個類的物件才算是完整的。另外,非靜態程式碼塊其實就是物件 new 的準備工作之一,算是一個不接受任何外來引數的構造方法。因此,屬性 > 非靜態程式碼塊 > 構造方法
  3. 有趣的是,靜態部分(前4個)是父類 > 子類,而 非靜態部分(後6個)也是父類 > 子類
  4. 另外容易忽略的是,非靜態程式碼塊在每次 new 物件時都會執行,可以理解:非靜態程式碼塊是正式構造方法前的準備工作(非靜態程式碼塊 > 構造方法)。

測試程式碼如下:

/**
 * @author Lean.Li
 * @date 2018/10/15
 */
public class Main {

    static class A {
        static Hi hi = new Hi("A");

        Hi hi2 = new Hi("A2");

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

        {
            System.out.println("AAA");
        }

        public A() {
            System.out.println("A init");
        }
    }


    static class B extends A {
        static Hi hi = new Hi("B");

        Hi hi2 = new Hi("B2");

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

        {
            System.out.println("BBB");
        }

        public B() {
            System.out.println("B init");
        }
    }

    static class Hi {
        public Hi(String str) {
            System.out.println("Hi " + str);
        }
    }

    public static void main(String[] args) {
        System.out.println("初次 new B:");
        B b = new B();
        System.out.println();
        System.out.println("第二次 new B:");
        b = new B();
    }

}

執行結果如下:

初次 new B:
Hi A
A static
Hi B
B static
Hi A2
AAA
A init
Hi B2
BBB
B init

第二次 new B:
Hi A2
AAA
A init
Hi B2
BBB
B init


相關文章