下面這個案例整合了繼承,靜態成員,構造器的執行順序以及就近原則問題的分析,看到很多面試題經常會出此類的題目,具體看例子。
父類:
public abstract class Fu {
static int count=3;
int a=3;
static{
System.out.println("父類的靜態代碼塊");
}
public Fu() {
a=5;
System.out.println("執行父類的構造方法");
}
public void display(){
System.out.println("父類的diaplay()方法");
System.out.println(a);
show();
}
public void show(){
System.out.println("父類的show方法");
}
}
子類:
public class Zi extends Fu {
static int count=10;
int a=6;
static{
System.out.println("子類的靜態代碼塊");
}
public Zi() {
System.out.println("執行子類的構造方法");
}
public void show(){
System.out.println("子類的show方法");
System.out.println(a);
}
}
測試類:
public class Test {
static{
System.out.println("測試類的靜態代碼塊!");
}
public static void main(String[] args) {
Zi zi = new Zi();
zi.display();
}
}
執行main(),會得到怎樣的結果呢?看控制檯的輸出結果:
測試類的靜態代碼塊! 1
父類的靜態代碼塊 2
子類的靜態代碼塊 3
執行父類的構造方法 4
執行子類的構造方法 5
父類的diaplay()方法 6
5 7
子類的show方法 8
6 9
下面是關於執行步驟的分析:
1.jvm加載含有main()的類,打印結果1
2.執行main(),創建子類對象,會在創建子類對象之前調用父類無參的構造方法,所以初始化父類,打印結果2
3.初始化完父類,初始化子類,打印結果3
4.執行父類的構造方法,完成父類的初始化,但不會創建父類對象(抽象類,即使不是抽象類,也不會創建父類對象,只有new,纔會創建對象)。打印結果4
5.執行子類的構造方法,準備創建子類對象,打印結果5
6,調用子類的display()方法,子類沒有重寫,所以調用父類的diaplay()方法,打印結果6
7.然後輸出父類的成員,就近原則(看圖)打印結果7
8.在display()中調用show()方法,子類覆蓋了其show(),子類的空間也有,調用的是子類的show()方法。打印結果8
9.最後就近,打印子類的成員,打印結果9
爲此我還爲繼承的關係畫了個內存圖
關於內存圖的需要解釋的地方:子類繼承父類時,創建子類對象以後,會在堆內存中給子類對象分配一塊內存空間,這個子類中空間中還存有一個父類的空間裝着父類的一些成員。可以總結爲,一塊地址,兩片空間。