假設有個名為Dog的類
對於靜態字段:
1. 當Dog類的靜態字段/靜態方法首次被訪問時(首次創建類型為Dog的對象時也會加載Dog.class文件,可以把構造器看做是static的),Java解釋器會查找類路徑,以定位Dog.class文件。
2. 載入Dog.class,此時初始化所有靜態字段,如果沒有對靜態字段進行顯示初始化,則默認將所有基本類型字段都設置成標准初值,而引用字段被設置成null。
對於非靜態字段:
1. 當創建類型為Dog的對象時,首先將在堆上為該對象分配存儲空間,且存儲空間會被清零,這就將所有基本類型字段都設置成了標准初值,而引用字段被設置成了null。
2. 執行所有出現於字段定義處的初始化動作。
3. 執行構造器。
假設類Dog有一個父類Animal
對於靜態字段:
1. 當Dog類的靜態字段/靜態方法首次被訪問時(首次創建類型為Dog的對象時也會加載Dog.class文件,可以把構造器看做是static的),Java解釋器會查找類路徑,以定位Dog.class文件。
2. 當載入Dog.class時,編譯器注意到它有一個父類Animal,於是繼續加載Animal.class,此時首先初始化類Animal的所有靜態字段,然後初始化類Dog的所有靜態字段。如果沒有對靜態字段進行顯示初始化,則默認將所有基本類型字段都設置成標准初值,而引用字段被設置成null。
對於非靜態字段:
1. 當創建類型為Dog的對象時,首先將在堆上為該對象分配存儲空間,且存儲空間會被清零,這就將所有基本類型字段都設置成了標准初值,而引用字段被設置成了null。
2. 執行子類Dog的構造器中的super()語句來調用父類Animal的構造器,這個過程通常是隱含進行的,詳情見Java常見問題之this()和super()的用法。父類Animal的構造器繼續按照步驟2、3、4的順序遞歸進行。
注意:如果父類的構造器中調用了被子類覆蓋的方法,則此時實際調用的是子類的方法,即在對象完全創建好之間,多態就已經開始發揮作用了,而此時子類對象的某些字段還沒有完成初始化,而如果該方法又使用了這些字段,則會出現邏輯錯誤,所以盡量不要在構造器中調用除final以外的方法。
3. 執行子類Dog中所有出現於字段定義處的初始化動作。
4. 執行子類Dog的構造器中的剩余部分。
注意:
靜態字段只會在加載class文件時進行一次初始化操作。
每次創建類型為Dog的對象時,都會對非靜態字段進行初始化操作。
靜態字段由Dog類的所有對象共享,只占用一份存儲區域。
非靜態字段是與Dog類的對象相關聯的,每個對象都有自己獨立的存儲區域。
當首次創建類型為Dog的對象時,會先初始化靜態字段,再初始化非靜態字段。
Dog類的靜態字段/靜態方法首次被訪問時,只會初始化靜態字段,不會初始化非靜態字段。