【Java基礎】類的實例化、static、父類構造函數執行順序



重溫java基礎,以免自己以後犯原則性錯誤,這是最基本,最基礎的東西。


直接上代碼:

A.java

public class A {

	int a1 = 8;
	int a2 = getA2();
	{
		int a3 = 9;
		System.out.println("top of A() a1=" + a1 + " a2=" + a2 + "  a3=" + a3);
	}

	public A() {
		this(66);
		System.out.print("A 構造函數\n");
	}

	{
		System.out.println("below A()..has start");
	}

	public A(int num) {
		System.out.print("A 帶參數構造函數: " + num + "\n");
	}

	static {
		System.out.println("I`m a static {} from class A..");
	}

	int getA2() {
		System.out.println("getA2..");
		return 7;
	}

	public void methodA() {
		System.out.println("methodA");
	}

}

B.java

public class B extends A {

	int b1 = 0;
	int b2 = getB2();
	{
		int b3 = 5;
		System.out.println("top of B() b1=" + b1 + " b2=" + b2 + " b3=" + b3);

	}

	public B() {
		this(33);
		// super(44);//添加super語句,會導致實例化時直接執行父類帶參數的構造函數
		System.out.print("B 構造函數\n");
	}

	public B(int num) {
		// 添加super語句,會導致實例化時直接執行父類帶參數的構造函數
		// 前提是帶參數的構造函數B會被運行(new實例化或this)
		// super(77);

		System.out.print("B 帶參數構造函數:" + num + "\n");
	}

	{
		System.out.println("below B()..has start");
	}
	static {
		System.out.println("I`m a static {} from class B..");
	}

	int getB2() {
		System.out.println("getB2..");
		return 33;

	}

	@Override
	public void methodA() {
		System.out.println("methoaA int class B");
		super.methodA();

	}

}

main.java

public class mymain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("main app run..");
		B b = new B();
//		B b = new B(22);
		b.methodA();
	}

}



實驗一


思考一下打印輸出的順序?


打印輸出結果:

main app run..

I`m a static {} from class A..

I`m a static {} from class B..

getA2..

top of A() a1=8 a2=7  a3=9

below A()..has start

A 帶參數構造函數: 66

A 構造函數

getB2..

top of B() b1=0 b2=33 b3=5

below B()..has start

B 帶參數構造函數:33

B 構造函數

methoaA int class B

methodA


分析:B類無參的構造函數中的this語句並沒有影響到父類A類的構造函數執行順序



***********************************分割線***********************************


實驗二


如果我把B類無參數的構造函數,this(33)換成super(44)呢,看一下結果?

main app run..

I`m a static {} from class A..

I`m a static {} from class B..

getA2..

top of A() a1=8 a2=7  a3=9

below A()..has start

A 帶參數構造函數: 44

getB2..

top of B() b1=0 b2=33 b3=5

below B()..has start

B 構造函數

methoaA int class B

methodA



分析:B類無參構造函數中的super語句直接影響了父類(A類)構造函數的執行順序,由於super(44)指向了父類帶參數的構造函數,造成實例化時,只執行了父類帶參數的構造函數,由此看出,super語句的有與無,對父類帶參/不帶參的構造函數是有影響的。


***********************************分割線***********************************


實驗三


如果B類無參數的構造函數,如一開始那樣this(33)保留,super去掉;但是B類帶參數的構造函數添加 super(77)語句,結果又會是什麼呢?

main app run..

I`m a static {} from class A..

I`m a static {} from class B..

getA2..

top of A() a1=8 a2=7  a3=9

below A()..has start

A 帶參數構造函數: 77

getB2..

top of B() b1=0 b2=33 b3=5

below B()..has start

B 帶參數構造函數:33

B 構造函數

methoaA int class B

methodA


分析:B類帶參數的構造函數中的super(77),又影響了父類構造函數的執行順序,導致父類沒有執行無參的構造函數,這一切都是因爲有super語句!但是請記住,因爲實例化B類無參的構造函數中有一句:this(33),使編譯器看到了B類帶參數構造函數中的super語句。假如說,沒有this(33)語句,並且B類new時並沒有new到帶參數的構造函數,此時編譯器並不會查找到super語句,也就繼續執行父類無參的構造函數,就像實驗一的結果一樣。



綜合結論:

一個類的實例化過程:

1,首先會執行類中static代碼塊(不管代碼塊是否在類的開頭還是末尾處),如果這個類有父類,同樣會優先查找父類中的static代碼塊,然後是當前類的static。


2,然後會從父類的第一行開始執行,直至代碼末尾處,中間不管是有賦值還是method調用,都會按順序一一執行(method),普通代碼塊{ }...


3,其次纔是父類的構造函數,執行帶參數或不帶參數的構造函數,依賴於實例化的類的構造函數有沒有super父類的帶參或不帶參的構造函數,上邊試驗二三已經證明。


4,然後會從子類(當前類)的第一行開始執行,直至代碼末尾處,中間不管是有賦值還是method調用,都會按順序一一執行(method),普通代碼塊{ }...


5,其次會是子類(當前類)的構造函數,按順序執行。


6,最後是類方法的調用執行,如果子類覆蓋了父類的method,執行時會先執行子類覆蓋的method,method內如果有super.method(),纔會調用父類的同名method,否則不會。


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