物件的建立過程,子父類中建構函式特點
物件的建立過程
類的載入過程:
- 啟動JVM,載入程式中需要使用的class檔案。
- 在載入class檔案的時候,所有的靜態內容(靜態成員變數,靜態成員函式,靜態程式碼塊)都要載入到方法區的靜態區中。
- 當類中的所有靜態載入完成之後,開始給類中的所有靜態成員變數預設初始化。
- 類中的所有靜態成員變數預設初始化完成之後,開始給這些靜態成員變數顯示賦值。
- 所有靜態成員變數顯示賦值結束之後,開始執行類中的靜態程式碼塊
- 當所有的靜態程式碼塊執行完成,代表當前這個class檔案才徹底被載入結束。
物件的建立過程:
- 使用new關鍵字建立物件,在堆給物件分配記憶體空間
- 給物件所屬類中的所有非靜態成員變數分配空間並進行預設的初始化
- 執行和new物件時傳遞引數一致的建構函式。
- 執行建構函式的的過程中有隱式的三步:
4.1、執行super() 語句,找父類的空引數建構函式
4.2、給成員變數進行顯示賦值。
4.3、構造程式碼塊執行
4.4、建構函式中的自己寫的程式碼執行。
5、建構函式執行完成,物件建立結束。
子父類中建構函式特點
在前面學習物件的建立流程中,在使用new關鍵字建立物件的時候,先在堆中給物件分配記憶體空間,接著給非靜態的成員變數進行預設初始化,開始呼叫對應的建構函式。而在執行建構函式中有隱式的三步:
- super(); 它是在呼叫自己的父類空引數的建構函式。
- 成員變數顯示賦值
- 構造程式碼塊執行
4、本建構函式中的程式碼執行。
class Fu{
int x = 3;
{
System.out.println("Fu 構造程式碼塊執行...x="+x);
}
Fu(){
System.out.println("Fu建構函式執行");
show();
}
public void show(){
System.out.println("Fu show...x="+x);
}
}
class Zi extends Fu{
int y = 10;
{
System.out.println("Zi 構造程式碼塊執行...x="+x);
System.out.println("Zi 構造程式碼塊執行...y="+y);
}
Zi(){
System.out.println("Zi 建構函式執行...");
show();
}
public void show(){
System.out.println("Zi show...x="+x);
System.out.println("Zi show...y="+y);
}
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
}
}
1.9、子類的例項化過程
1、為什麼任何一個類(不包含Object)的建構函式中需要一個隱式的super() 語句?
因為任何的子類在繼承了父類之後,都會繼承到父類的成員變數,這時在建立子類物件的時候,會在子類的物件空間中分配出空間儲存父類的成員變數。而父類的成員變數初始化動作必須由父類的自己的建構函式完成。所以在任何類的建構函式中有一個隱式的super()語句。
2、如果一個類中的所有建構函式全部私有了,問還可以有子類嗎?子類能例項化嗎?
一個類的建構函式全部私有,這時這個類是無法再有子類的。就不存在例項化問題。
3、如果一個類沒有空引數的建構函式,問這個類可以有子類嗎?子類可以例項化嗎?
如果這個類還有其他的建構函式可以被訪問,那麼這個類就可以有子類。
這是要求在子類的建構函式中必須手動的書寫super語句,同時在super( 具體的引數 )。根據指定的引數去呼叫父類型別相同的建構函式。
4、this呼叫建構函式可以和super呼叫父類建構函式共存嗎?
不可以。因為this和super呼叫建構函式都必須在建構函式中的第一行。
this是呼叫本類其他建構函式對當前這個物件初始化,而super是呼叫父類建構函式進行初始化,而初始化動作在一個建構函式中只能有一個。
在一個類中有多個建構函式,之間可以使用this呼叫,但不能形成巢狀呼叫。最後肯定有一個建構函式中是沒有this呼叫的,最後它中必然會有super語句呼叫父類的建構函式。