淺談Java類加載順序

之前一直搞錯,這裏總結一下java類加載順序
一個類中主要有如下成員:
普通對象變量,靜態對象變量,靜態方法,普通代碼塊,靜態代碼塊,普通方法。

總體規則:
靜態在非靜態之前初始化(無論父類還是子類)
先初始化父類,再初始化子類,子類只有靜態初始在父類其他非靜態初始之前,其他等父類初始化完畢,再初始化自己
靜態對象變量,靜態代碼塊初始化順序看具體代碼順序
普通對象變量,普通代碼塊初始化順序看具體代碼順序
構造函數在最後,無論書寫順序
靜態方法,普通方法調用時才初始化
銷燬時,先銷燬子類,再銷燬父類
靜態變量,靜態代碼塊只初始化一次

例子:

提供測試的Name.java

public class Name {
    public Name(String value) {
        System.out.println(value);
    }
}

父類Animal.java

public class Animal {

    static {
        System.out.println("father: static code block");
    }

    public Animal() {
        System.out.println("father: constructor");
    }

    Name n1 = new Name("father: variable");

    {
        System.out.println("father: code block");
    }

    static Name n2 = new Name("father: static variable");

}

子類Bird.java

public class Animal {

    static {
        System.out.println("father: static code block");
    }

    public Animal() {
        System.out.println("father: constructor");
    }

    Name n1 = new Name("father: variable");

    {
        System.out.println("father: code block");
    }

    static Name n2 = new Name("father: static variable");

}

運行結果:

father: static code block
father: static variable
child: static variable
child: static code block
father: variable
father: code block
father: constructor
child: code block
child: variable
child: constructor

子類初始化時候,默認尋找父類不帶參數的構造函數,如果找不到,那就說明父類提供了一個帶參的構造函數,那麼子類必須用super關鍵字顯示調用,而且必須放在自己構造函數第一行。而且此時只用帶參的構造函數初始化。
例子:修改Animal.java

public class Animal {

    static {
        System.out.println("father: static code block");
    }

    public Animal() {
        System.out.println("father: constructor");
    }

    public Animal(int i) {
        System.out.println("father: constructor parameter");
    }

    Name n1 = new Name("father: variable");

    {
        System.out.println("father: code block");
    }

    static Name n2 = new Name("father: static variable");

}

修改Bird.java

public class Bird extends Animal {
    static Name n4 = new Name("child: static variable");

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

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

    Bird() {
        super(1);
        System.out.println("child: constructor");
    }

    Name n3 = new Name("child: variable");

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

執行結果:

father: static code block
father: static variable
child: static variable
child: static code block
father: variable
father: code block
father: constructor parameter
child: code block
child: variable
child: constructor

注意:
如果我將代碼main函數修改爲如下這個樣子,那麼輸出結果是什麼呢?

public static void main(String[] args) {
        System.out.println("before main");
        new Bird();
    }

執行結果:

father: static code block
father: static variable
child: static variable
child: static code block
before main
father: variable
father: code block
father: constructor parameter
child: code block
child: variable
child: constructor

爲什麼呢?
執行main函數之前,java先加載這個類,static是類變量,因此需要先執行。如果我們在另外一個函數裏面寫上述main函數,那麼before main就打印了,請看:
Client.java

public class Client {
    public static void main(String[] args) {
        System.out.println("before main");
        new Bird();
    }
}

執行結果:

before main
father: static code block
father: static variable
child: static variable
child: static code block
father: variable
father: code block
father: constructor parameter
child: code block
child: variable
child: constructor

再測試一下,靜態變量只初始化一次
Client.java

public class Client {
    public static void main(String[] args) {
        System.out.println("before main");
        new Bird();
        System.out.println("second initial");
        new Bird();
    }
}

執行結果:

before main
father: static code block
father: static variable
child: static variable
child: static code block
father: variable
father: code block
father: constructor parameter
child: code block
child: variable
child: constructor
second initial
father: variable
father: code block
father: constructor parameter
child: code block
child: variable
child: constructor
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章