類的初始化&例項化順序
阿新 • • 發佈:2019-02-15
講到類的初始化和例項化(見我的《Class的生命週期》),不得不提提初始化和例項化的順序,我想這也是一直困擾了很大一部分人。
從大流程來說,類肯定是先初始化,再例項化的,這裡得出第一個順序:
靜態域 --> 例項域 --> 建構函式。另外要符合任何子類的動作都會觸發父類:父類 --> 子類。所以得出原則:【先靜態後例項;先父類後子類】
而且同一個域的順序可以分成兩步: 建立-->賦值
對於靜態域,其先經過連結建立靜態變數,賦default值;再到初始化階段給靜態變數賦assign值和執行靜態程式碼塊。同理於例項域,也是分成建立和賦值兩個部分,不同的只是加入建構函式(形參和程式碼塊):先建立例項變數和建構函式形參以default值,然後對變數和形參賦assign值和執行例項程式碼塊,最後執行建構函式的程式碼。
前提先要執行父類,再到子類;另外同一層次的就按從上到下順序執行,如下面例子。
package com.jscai.java.classLoader; public class LoaderLazy { { System.out.println("Parent Instance Code"); } private PrintTmp p1 = new PrintTmp("Parent Instance Member"); static { System.out.println("Parent Static Code"); } private static PrintTmp p2 = new PrintTmp("Parent Static Member"); public LoaderLazy() { System.out.println("Parent Constuctor"); } } class SubLoaderLazy extends LoaderLazy { { System.out.println("Sub Instance Code"); } private PrintTmp p1 = new PrintTmp("Sub Instance Member"); static { System.out.println("Sub Static Code"); } private static PrintTmp p2 = new PrintTmp("Sub Static Member"); public SubLoaderLazy() { System.out.println("Sub Constuctor"); } } class PrintTmp { public PrintTmp(String strOut) { System.out.println(strOut); } } SubLoaderLazy test = new SubLoaderLazy();
console:
Parent Static Code
Parent Static Member
Sub Static Code
Sub Static Member
Parent Instance Code
Parent Instance Member
Parent Constuctor
Sub Instance Code
Sub Instance Member
Sub Constuctor
另外我們看看下面的程式碼,說明了靜態域先賦default值;然後按順序賦assign值,先執行tester = new Test(),這時候count1和count2還是0,所以自加後都是1。
private static Test tester = new Test();
private static int count1;
private static int count2 = 2;
public Test() {
count1++;
count2++;
System.out.println("c1=" +count1 + "; c2=" + count2);
}
console:
c1=1; c2=1