1. 程式人生 > >Java 物件初始化順序 執行順序

Java 物件初始化順序 執行順序

先看一道Java面試題:

求這段程式的輸出。

解答此題關鍵在於理解和掌握類的載入過程以及子類繼承父類後,重寫方法的呼叫問題:

從程式的執行順序去解答:

1.編譯;當這個類被編譯通知後,會在相應的目錄下生成兩個.class 檔案。一個是 Base.class,另外一個就是Base$Sub.class。這個時候類載入器將這兩個.class  檔案載入到記憶體

2、Base base= new Sub():

  宣告父類變數base對子類的引用,JAVA類載入器將Base,Sub類載入到JVM(Java虛擬機器);

3、JVM為Base,Sub 的的成員開闢記憶體空間

  此時,Base 和Sub類中的值為null;

4、new Sub();

  這個時候會呼叫Sub類的隱式構造方法,

     Sub的構造方法本質為:

     public Sub(){

  super();//  呼叫父類的構造方法必須在構造方法中的第一行,為什麼呢?這是因為在一些程式的升級中,要相容舊版本的一些功能,父類即原先的一些初始化資訊也要保證  //被執行到,然後執行當前

  baseName = "sub";//子類欄位初始化

      }

    new Sub()執行到super()這行程式碼也就是跑到父類中去執行了,我們跳轉到父類中的無參構造方法中執行,最後執行Sub()中的baseName = "sub";

5、public Base() ;

      父類無參構造方法的本質為:

  public Base(){

  baseName= "base";//父類欄位初始化

  callName();

    }

  即將父類的baseName賦值為“base”,賦值後呼叫callName();

6、callName()方法在子類中被重寫,因此呼叫子類的callName(),子類的callName方法執行,列印輸出的是子類的baseName 欄位的值,而這個時候子類的建構函式中欄位的賦值還未執行。

7、父類的建構函式執行完畢,這個時候又回到子類當中,從super()的下一行繼續執行,這個時候才為子類欄位baseName 分配好儲存空間,隨後為其賦值:

 可見,在baseName = "sub"執行前,子類的callName()已經執行,所以子類的baseName為預設值狀態null;

二、總結

java物件初始化順序
1.父類靜態初始化方法 static{ }
2.子類靜態初始化方法 static{ }
3.父類欄位初始化 ,如private String name ="base"
4.父類非靜態初始化方法 {}
5.父類構造方法
6.子類欄位初始化,如private String name="sub";
7.子類非靜態初始化方法{}
8 子類構造方法