1. 程式人生 > >【Java基礎】類的例項化、static、父類建構函式執行順序

【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,否則不會。