1. 程式人生 > >靜態成員變數靜態程式碼塊和構造方法的執行順序

靜態成員變數靜態程式碼塊和構造方法的執行順序

型別一:靜態成員變數+非靜態成員變數+構造方法

public class StaticInitialization {

    public static void main(String[] args) {
        System.out.println("creating new Cupboard() in main");
        new Cupboard();
        System.out.println("creating new Cupboard() in main");
        new Cupboard();
        table.f2(1);
        cupboard.f3(1
); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); } class Bowl{ public Bowl(int marker){ System.out.println("Bowl("+marker+")"); } void f1(int marker){ System.out.println("f1("+marker+")"); } } class Table{ static Bowl bowl1 = new
Bowl(1); static Bowl bowl2 = new Bowl(2); public Table(){ System.out.println("Table()"); bowl2.f1(1); } void f2(int marker){ System.out.println("f2("+marker+")"); } } class Cupboard{ Bowl bowl3 = new Bowl(3); static Bowl bowl4 = new Bowl(4); static
Bowl bowl5 = new Bowl(5); public Cupboard(){ System.out.println("Cupboard()"); bowl4.f1(2); } void f3(int marker){ System.out.println("f3("+marker+")"); } }

**輸出結果:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)**
總結:
1、要執行main方法首先要載入StaticInitialization這個類。所以先初始化了StaticInitialization裡面的兩個靜態成員變數。
2、當table被初始化的時候列印:Bowl(1) Bowl(2) Table() f1(1);
3、當cupboard 被初始化的時候列印:Bowl(4) Bowl(5) Bowl(3) Cupboard() f1(2)(注意:因為初始化的時候會先載入靜態成員變數或者靜態程式碼塊,這個要看在類中放的順序的,優先載入前面的,載入完了靜態成員變數再載入非靜態成員變數再執行構造方法);
4、執行main方法,因為staic靜態成員變數只會初始化一次,所以列印:creating new Cupboard() in main Bowl(3) Cupboard() f1(2) creating new Cupboard() in main Bowl(3) Cupboard() f1(2)。
5、最後列印:f2(1) f3(1)。

型別二:靜態成員變數+靜態程式碼塊+構造方法

public class StaticInitialization2 {

    //static Cups cups1 = new Cups();//(2)
    //static Cups cups2 = new Cups();//(2)

    public static void main(String[] args) {
        System.out.println("Inside main");
        Cups.cup1.f(99);//(1)
    }
}

class Cup{

    public Cup(int marker){
        System.out.println("Cup("+marker+")");
    }

    void f(int marker){
        System.out.println("f("+marker+")");
    }
}

class Cups{
    static Cup cup1;
    static Cup cup2;
    static Cup cup3 = new Cup(3);
    static {
        cup1 = new Cup(1);
        cup2 = new Cup(2);
    }

    public Cups(){
        System.out.println("Cups()");
    }

}

**輸出結果:
Inside main
Cup(3)
Cup(1)
Cup(2)
f(99)
**
總結:先執行main方法,列印Inside main;
當一個類被首次new創建出來或者首次訪問這個類的靜態成員變數或者呼叫靜態方法時才會初始化,而且只建立一次,不同點是new出來會呼叫構造方法,而用類名點屬性或者方法的方式不會呼叫構造方法;
從這裡可以看出靜態成員變數和靜態程式碼塊的執行順序無優先順序關係,只和在類裡面的位置有關;

當吧(2)中的註釋放開
**輸出結果:
Cup(3)
Cup(1)
Cup(2)
Cups()
Cups()
Inside main
f(99)**
總結:說明靜態成員變數只會初始化一次,new出來的構造方法會執行多次;

型別三:非靜態例項初始化

public class Mugs {

    Mug mug1;
    Mug mug2;
    {
        mug1 = new Mug(1);
        mug2 = new Mug(2);
        System.out.println("mug1 和 mug2初始化了");
    }

    public Mugs(){
        System.out.println("Mugs()");
    }

    public Mugs(int i){
        System.out.println("Mugs(int)");
    }

    public static void main(String[] args) {
        System.out.println("Inside main()");
        new Mugs();
        System.out.println("new Mugs() completed");
        new Mugs(1);
        System.out.println("new Mugs(1) completed");
    }
}

class Mug{
    public Mug(int marker) {
        System.out.println("Mug("+marker+")");
    }
    void f(int marker){
        System.out.println("f1("+marker+")");
    }
}

輸出結果:
**Inside main()
Mug(1)
Mug(2)
mug1 和 mug2初始化了
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 和 mug2初始化了
Mugs(int)
new Mugs(1) completed**
總結:1、先是執行main方法,列印:Inside main()
2、new Mugs(),這時候列印:Mug(1) Mug(2) mug1 和 mug2初始化了 Mugs()
3、在列印:new Mugs() completed
4、new Mugs(2),列印:Mug(1) Mug(2) mug1 和 mug2初始化了 Mugs(int)
5、最後執行:new Mugs(1) completed
其實可以把
{
mug1 = new Mug(1);
mug2 = new Mug(2);
System.out.println(“mug1 和 mug2初始化了”);
}
當做一個普通的成員變數來執行,只不過有一些特殊,每次建立都會執行,也沒有優先順序;