1. 程式人生 > >類的初始化&例項化順序

類的初始化&例項化順序

講到類的初始化和例項化(見我的《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