類加載之 <clinit>() 和 <init>()

前序文章:深入理解Java類加載

<clinit>() 與 <init>() 區(qū)別

<clinit>()

Java 類加載的初始化過程中,編譯器按語句在源文件中出現(xiàn)的順序,依次自動(dòng)收集類中的所有類變量的賦值動(dòng)作和靜態(tài)代碼塊中的語句合并產(chǎn)生 <clinit>() 方法。 如果類中沒有靜態(tài)語句和靜態(tài)代碼塊,那可以不生成<clinit>()` 方法。

并且 <clinit>() 不需要顯式調(diào)用父類(接口除外,接口不需要調(diào)用父接口的初始化方法,只有使用到父接口中的靜態(tài)變量時(shí)才需要調(diào)用)的初始化方法 <clinit>(),虛擬機(jī)會(huì)保證在子類的 <clinit>() 方法執(zhí)行之前,父類的 <clinit>() 方法已經(jīng)執(zhí)行完畢。

<init>()

對(duì)象構(gòu)造時(shí)用以初始化對(duì)象的,構(gòu)造器以及非靜態(tài)初始化塊中的代碼。

<clinit>() 與 <init>() 執(zhí)行順序

直接看代碼

public class Test {
    private static Test instance;

    static {
        System.out.println("static開始");
        // 下面這句編譯器報(bào)錯(cuò),非法向前引用
        // System.out.println("x=" + x);
        instance = new Test();
        System.out.println("static結(jié)束");
    }

    public Test() {
        System.out.println("構(gòu)造器開始");
        System.out.println("x=" + x + ";y=" + y);
        // 構(gòu)造器可以訪問聲明于他們后面的靜態(tài)變量
        // 因?yàn)殪o態(tài)變量在類加載的準(zhǔn)備階段就已經(jīng)分配內(nèi)存并初始化0值了
        // 此時(shí) x=0,y=0
        x++;
        y++;
        System.out.println("x=" + x + ";y=" + y);
        System.out.println("構(gòu)造器結(jié)束");
    }

    public static int x = 6;
    public static int y;

    public static Test getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        Test obj = Test.getInstance();
        System.out.println("x=" + obj.x);
        System.out.println("y=" + obj.y);
    }
}

輸出信息如下:

static開始
構(gòu)造器開始
x=0;y=0
x=1;y=1
構(gòu)造器結(jié)束
static結(jié)束
x=6
y=1

虛擬機(jī)首先執(zhí)行的是類加載初始化過程中的 <clinit>() 方法,也就是靜態(tài)變量賦值以及靜態(tài)代碼塊中的代碼,如果 <clinit>() 方法中觸發(fā)了對(duì)象的初始化,也就是 <init>() 方法,那么會(huì)進(jìn)入執(zhí)行 <init>() 方法,執(zhí)行 <init>() 方法完成之后,再回來繼續(xù)執(zhí)行 <clinit>() 方法。

上面代碼中,先執(zhí)行 static 代碼塊,此時(shí)調(diào)用了構(gòu)造器,構(gòu)造器中對(duì)類變量 x 和 y 進(jìn)行加 1 ,之后繼續(xù)完 static 代碼塊,接著執(zhí)行下面的 public static int x = 6; 來重新給類變量 x 賦值為 6,因此,最后輸出的是 x=6, y=1。

如果希望輸出的是 x=7,y=1,很簡單,將語句 public static int x = 6; 移至 static 代碼塊之前就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容