類加載的時機

  類從被加載到虛擬機內存中開始,直到卸載出內存爲止,它的整個生命週期包括了:加載、驗證、準備、解析、初始化、使用和卸載這7個階段。其中,驗證、準備和解析這三個部分統稱爲鏈接(linking)html

  一、類什麼時候進行初始化java

    a,建立實例面試

    b,調用非final的靜態方法和靜態變量數組

    c,初始化類時,會先初始化父類安全

    d,反射到一個類數據結構

    e,虛擬機啓動時會優先初始化含有main()函數的類函數

    以上爲主動引用佈局

 

    被動引用spa

    f,子類調用父類的靜態變量,子類不會被初始化。只有父類被初始化。。對於靜態字段,只有直接定義這個字段的類纔會被初始化.指針

    g,經過數組定義來引用類,不會觸發類的初始化

    h,訪問類的常量,不會初始化類

 

  二、類加載過程

    a加載,

       「加載」(Loading)階段是「類加載」(Class Loading)過程的第一個階段,在此階段,虛擬機須要完成如下三件事情:

             一、 經過一個類的全限定名來獲取定義此類的二進制字節流。

             二、 將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構。

             三、 在Java堆中生成一個表明這個類的java.lang.Class對象,做爲方法區這些數據的訪問入口。

            加載階段便可以使用系統提供的類加載器在完成,也能夠由用戶自定義的類加載器來完成。加載階段與鏈接階段的部份內容(如一部分字節碼文件格式驗證動做)是交叉進行的,加載階段還沒有完成,鏈接階段可能已經開始

    b驗證,

      驗證是鏈接階段的第一步,這一階段的目的是爲了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,而且不會危害虛擬機自身的安全。

    c準備,      

      準備階段是爲類的靜態變量分配內存並將其初始化爲默認值,這些內存都將在方法區中進行分配。準備階段不分配類中的實例變量的內存,實例變量將會在對象實例化時隨着對象一塊兒分配在Java堆中。

            public static int value=123;//在準備階段value初始值爲0 。在初始化階段纔會變爲123 。

    d解析,     

       解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程。

           符號引用(Symbolic Reference):符號引用以一組符號來描述所引用的目標,符號能夠是任何形式的字面量,只要使用時能無歧義地定位到目標便可。符號引用與虛擬機實現的內存佈局無關,引用的目標並不必定已經加載到內存中。

           直接引用(Direct Reference):直接引用能夠是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。直接引用是與虛擬機實現的內存佈局相關的,若是有了直接引用,那麼引用的目標一定已經在內存中存在。

    e初始化,

        類初始化是類加載過程的最後一步,前面的類加載過程,除了在加載階段用戶應用程序能夠經過自定義類加載器參與以外,其他動做徹底由虛擬機主導和控制。到了初始化階段,才真正開始執行類中定義的Java程序代碼。

            初始化階段是執行類構造器<clinit>()方法的過程。<clinit>()方法是由編譯器自動收集類中的全部類變量的賦值動做和靜態語句塊(static{}塊)中的語句合併產生的。

  三、面試題解析

    

class SingleTon {
    private static SingleTon singleTon = new SingleTon();
    public static int count1;
    public static int count2 = 0;
 
    private SingleTon() {
        count1++;
        count2++;
    }
 
    public static SingleTon getInstance() {
        return singleTon;
    }
}
 
public class Test {
    public static void main(String[] args) {
        SingleTon singleTon = SingleTon.getInstance();
        System.out.println("count1=" + singleTon.count1);
        System.out.println("count2=" + singleTon.count2);
    }
}

輸出結果:

    1

    0

 

一、SingleTon.getInstance();調用類的靜態方法進行類初始化;
二、類加載的時候在準備過程當中爲類的靜態變量分配內存並初始化默認值 singleton=null count1=0,count2=0
三、類初始化化,爲類的靜態變量賦值和執行靜態代碼快。因爲靜態方法是按順序執行的。因此先執行構造方法,獲得new SungkeTon(),count1=1,count2=1,下一步執行count1 count2的初始化操做,
  因爲count1沒有初始化賦值操做,因此爲1。count2賦值後爲0
 
class SingleTon {

    public static int count1;
    public static int count2 = 0;
    private static SingleTon singleTon = new SingleTon();
 
    private SingleTon() {
        count1++;
        count2++;
    }
 
    public static SingleTon getInstance() {
        return singleTon;
    }
}
 
public class Test {
    public static void main(String[] args) {
        SingleTon singleTon = SingleTon.getInstance();
        System.out.println("count1=" + singleTon.count1);
        System.out.println("count2=" + singleTon.count2);
    }
}

輸出:1 1

 

 

出處:http://www.cnblogs.com/javaee6/p/3714716.html
相關文章
相關標籤/搜索