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