java靜態/動態成員變量、初始化塊,父類/子類構造函數執行順序問題

package job;

public class TestConsSeq {

	public static void main(String[] args) {
		/*
		 * 幾大原則
		 * 一、靜態成員變量(Static)
		 * 	1、靜態成員變量爲類變量,所有對象共享同一內存空間
		 * 	2、靜態成員變量的聲明和定義僅在首次加載類時執行一次
		 * 	3、首次加載類時首先對所有靜態成員變量根據類型默認賦初值,然後再對有右值的附右值
		 * 二、靜態初始塊
		 * 	1、靜態初始化塊僅在首次加載類時執行一次
		 * ······多個靜態成員變量與靜態始化快參照出現順序先後執行······
		 * 三、動態成員變量
		 * 	1、動態成員變量定義在每次實例化對象時在構造函數之前執行
		 * 四、動態初始化塊
		 * 	1、動態初始化塊在每次實例化對象時在構造函數之前執行
		 * ······多個動態成員變量與動態初始化塊參照出現順序先後執行······
		 * 總結:總的來說,在不涉及繼承的前提下,當首次加載類時,按照如下順序執行
		 * 	1、按照出現順序先後執行靜態成員變量定義與靜態初始化塊
		 * 	2、按照出現順序先後執行動態成員變量定義與動態初始化塊
		 * 	3、執行構造函數
		 * 	再次實例化對象時只執行第2、3步即可
		 * 
		 * ············成員變量與定義與初始化塊先於構造函數執行·········
		 * 五、當涉及到繼承時,按照如下順序執行
		 * 	1、執行父類的靜態成員變量定義與靜態初始化塊,執行子類的靜態成員變量定義與靜態初始化塊
		 * 	2、執行父類的非靜態成員變量定義與動態初始化塊,執行父類構造方法
		 * 	3、執行子類的非靜態成員變量定義與動態初始化塊,執行子類構造方法
		 * 另:父類構造方法中用到的方法如果已被子類重寫,那麼在構造子類對象時在調用父類構造函數中使用子類重寫的方法
		 */	
		int i = 0;
		switch(i) {
		case 0:
			
			new A();
			new A();
			
			break;
		case 1:
			
			A ab = new B();
			
			break;
		case 2 :
			
			C c1 = new C();
			System.out.println("c.i1 = " + c1.i1);//2
			System.out.println("c.i2 = " + c1.i2);//3
			
			break;
		} 
        /* 對i=2時的解釋
         * 爲什麼是2和3呢?
         * 其實代碼的執行順序是這樣的:在初始化c1的時候首先加載類
         * 定義靜態變量t1,i1,i2並賦初值null,0,0
         * 然後計算右值表達式new C(),準備將此對象賦給靜態成員變量c
         * 		然而上步中靜態成員變量已定義,直接執行c的構造函數即可
         * 		這樣i1++,i2++被執行,i1,i2都變爲1
         * 繼續執行到int i1;沒有賦值語句, i1,i2的值仍然是1
         * 繼續執行到int i2 = 2時i2被賦值2,即i1 = 1,i2 = 2
         * 繼續執行到c1的構造函數,i1,i2再執行++,此時i1 = 2,i2 = 3
         * 輸出i1,i2,結果就是:c1.i1 = 2,c1.i2 = 3
         * 通過上面的代碼我們可以認爲系統默認值的給予比通過等號的賦予先執行。
         */
	}
}

class A {
	public A() {
		System.out.println("construct A");
		m();
		System.out.println();
	}
	
	private int ai = getAI();
	
	{
		System.out.println("dynamic block in A");
	}

	static {
		System.out.println("static block in A");
	}
	
	private static int asi = getASI();
	
	static int getASI() {
		System.out.println("initial static int asi");
		System.out.println();
		return 5;
	}
	
	static int getAI() {
		System.out.println("initial int ai");
		return 10;
	}
	
	public void m() {
		System.out.println("A.m()");
	}
}

class B extends A{
	public B() {
		System.out.println("construct B");
		super.m();
		m();
	}
	
	{
		System.out.println("dynamic block in B");	
	}
	private int bi = getBI();
	private static int bsi = getBSI();

	
	static {
		System.out.println("static block in B");
		System.out.println();
	}
	
	static int getBSI() {
		System.out.println("initial static int bsi");
		return 5;
	}
	
	static int getBI() {
		System.out.println("initial int bi");
		return 10;
	}
	
	public void m() {
		System.out.println("B.m() bi=" + bi);
	}
}

class C{
    private static C c = new C();
    public static int i1;
    public static int i2 = 2;
    
    public C(){
        i1++;
        i2++;
    }
}

i=0時輸出:

static block in A
initial static int asi

initial int ai
dynamic block in A
construct A
A.m()

initial int ai
dynamic block in A
construct A
A.m()

i=1時輸出:

static block in A
initial static int asi

initial static int bsi
static block in B

initial int ai
dynamic block in A
construct A
B.m() bi=0

dynamic block in B
initial int bi
construct B
A.m()
B.m() bi=10

i=2時輸出

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