Java中類的加載順序剖析

這實際上是去年校招時的一道阿里巴巴的筆試題,若是沒記錯的話,當時是做爲Java方向的一道選作大題。固然題意沒有這麼直白,題目只要求你寫出程序運行後全部System.out.println的輸出結果,其中程序是題目給的,而各個System.out.println的執行順序不一樣會致使最後程序輸出的結果也不一樣。java

具體的題目我確定記不清,不過咱們能夠換個直接的問法,若是類A和類B中有靜態變量,靜態語句塊,非靜態變量,非靜態語句塊,構造函數,靜態方法,非靜態方法,同時類A繼承類B,請問當實例化A時,類內部的加載順序是什麼?函數

當時我也是一頭霧水,過後我就本身寫了一個小Demo,這才知道了類內部的實際加載順,測試代碼以下:測試

Class B:code

public class B{
//靜態變量  
static int i=1;
//靜態語句塊
static {
    System.out.println("Class B1:static blocks"+i);
}
//非靜態變量
int j=1;
//靜態語句塊
static{
    i++;
    System.out.println("Class B2:static blocks"+i);
}
//構造函數
public B(){
    i++;
    j++;
    System.out.println("constructor B: "+"i="+i+",j="+j);
}
//非靜態語句塊
{
  i++;
  j++;
  System.out.println("Class B:common blocks"+"i="+i+",j="+j);
}
//非靜態方法
public void bDisplay(){
    i++;
    System.out.println("Class B:static void bDisplay(): "+"i="+i+",j="+j);
    return ;
}
//靜態方法
public static void bTest(){
    i++;
    System.out.println("Class B:static void bTest():    "+"i="+i);
    return ;
}
}

Class A:對象

public class A extends B{
//靜態變量  
static int i=1;
//靜態語句塊
static {
    System.out.println("Class A1:static blocks"+i);
}
//非靜態變量
int j=1;
//靜態語句塊
static{
    i++;
    System.out.println("Class A2:static blocks"+i);
}
//構造函數
public A(){
    super();
    i++;
    j++;
    System.out.println("constructor A: "+"i="+i+",j="+j);
}
//非靜態語句塊
{
  i++;
  j++;
  System.out.println("Class A:common blocks"+"i="+i+",j="+j);
}
//非靜態方法
public void aDisplay(){
    i++;
    System.out.println("Class A:static void aDisplay(): "+"i="+i+",j="+j);
    return ;
}
//靜態方法
public static void aTest(){
    i++;
    System.out.println("Class A:static void aTest():    "+"i="+i);
    return ;
}
}

Class ClassLoading :繼承

public class ClassLoading {
     
    public static void main (String args[]) {
        A a=new A();
        a.aDisplay();
    }
}

程序運行結果如圖:class

經過上述示圖,咱們能夠比較清晰的看出java類的整個加載過程。阿里巴巴

1.若要加載類A,則先加載執行其父類B(Object)的靜態變量以及靜態語句塊(執行前後順序按排列的前後順序)。
2.而後再加載執行類A的靜態變量以及靜態語句塊。(而且一、2步驟只會執行1次)
3.若需實例化類A,則先調用其父類B的構造函數,而且在調用其父類B的構造函數前,依次先調用父類B中的非靜態變量及非靜態語句塊.最後再調用父類B中的構造函數初始化。
4.而後再依次調用類A中的非靜態變量及非靜態語句塊.最後調用A中的構造函數初始化。( 而且三、4步驟能夠重複執行)
5.而對於靜態方法和非靜態方法都是被動調用,即系統不會自動調用執行,因此用戶沒有調用時都不執行,主要區別在於靜態方法能夠直接用類名直接調用(實例化對象也能夠),而非靜態方法只能先實例化對象後才能調用。變量

相關文章
相關標籤/搜索