首先,我們先來看看下面的程式碼,這就是很經典的考察方式。
public class InitField { public static void main(String[] args) { SuperInitField p = new SuperInitField(); SuperInitField c = new SubInitField(); } } class SuperInitField { public SuperInitField() { System.out.println("parent"); } static { System.out.println("static parent"); } } class SubInitField extends SuperInitField { public SubInitField() { System.out.println("child"); } static { System.out.println("static child"); } }
不管你能不能很快速的寫出正確的答案,我們先把這個程式放一邊,了解Java虛擬機器初始化的原理。
JVM透過加裝、連接和初始化一個Java類型,使該類型可以被正在執行的Java程式所使用。類型的生命週期如下圖所示:
裝載和連接必須在初始化之前就要完成。
類別初始化階段,主要是為類別變數賦予正確的初始值。這裡的「正確」初始值指的是程式設計師希望這個類別變數所具備的起始值。一個正確的初始值是透過類別變數初始化語句或靜態初始化語句給出的。初始化一個類別包含兩個步驟:
1) 如果類別存在直接超類別的話,且直接超類別還沒有被初始化,就先初始化直接超類別。
2) 如果類別存在一個類別初始化方法,就執行此方法。
那什麼時候類別會進行初始化呢? Java 虛擬機器規格為類別的初始化時機做了嚴格定義:在***主動使用時初始化。
那哪些情形才符合***主動使用的標準呢? Java虛擬機器規格對此做了說明,他們分別是:
1) 建立類別的新實例;
2) 呼叫類別的靜態方法;
3)操作類別或介面的靜態欄位(final欄位除外);
4) 呼叫Java的特定的反射方法;
5) 初始化一個類別的子類別;
# 6) 指定一個類別作為Java虛擬機器啟動時的初始化類別。
除了以上六種情形以外,所有其它的方式都是被動使用的,不會導致類別的初始化。
一旦一個類別被裝載、連接和初始化,它就隨時可以使用了。現在我們來關注物件的實例化,物件實例化和初始化是就是物件生命的起始階段的活動。
Java編譯器為它編譯的每個類別都至少產生一個實例初始化方法,即
一個
如果建構方法是明確地從呼叫同一個類別中的另一個建構方法開始,那麼它對應的
一個對本類別的
#實作了對應建構方法的方法體的字節碼。
如果建構方法不是透過呼叫自身類別的其它建構方法開始,且該物件不是Object 對象,那麼
一個父類別的
任意實例變數初始化方法的字節碼;
實作了對應建構方法的方法體的字節碼。
透過上面的講解是不是對你理解Java類型的初始化有一定的幫助呢?
好,那我們再來分析一下開始的那段程式碼:
SuperInitField p = new SuperInitField(); //SuperInitField的超类是Object //创建SuperInitField对象,属于***主动使用,因此要先初始化Object类,然后再调用SuperInitField类变量初始化语句或者静态初始化语句,所以要输出static parent //类被装载、连接和初始化之后,创建一个对象,因此需要首先调用了Object的默认构造方法,然后再调用自己的构造方法,所以要输出parent SuperInitField c = new SubInitField(); //SubInitField继承自SuperInitField //创建SubInitField对象,属于***主动使用,父类SuperInitField已被初始化,因此只要调用SubInitField类变量初始化语句或者静态初始化语句,所以要输出static child //类被装载、连接和初始化之后,创建一个对象,因此需要首先调用了SuperInitField的构造方法,然后再调用自己的构造方法,所以要输出parent,然后再输出child
到現在你應該大體了解了Java類別初始化的原理了吧,那我就留一到練習題吧,寫出下列程式碼的運行結果。
public class Test { public Test(){ System.out.println("parent"); } static{ System.out.println("static parent"); } public static void main(String[] args) { System.out.println("main"); } }
以上是Java如何初始化類別與物件的詳細內容。更多資訊請關注PHP中文網其他相關文章!