java類載入中不會觸發初始化的被動引用

2021-08-27 19:18:29 字數 1436 閱讀 6668

我們知道,在初始化乙個類時,如果它的父類沒有進行初始化,那麼jvm就會觸發其父類的初始化動作。但是,當我們引用類的時候,可不一定會觸發其初始化,這種引用類的方式稱為[size=medium][color=red]被動引用[/color][/size]。

看下面的例子:

public class notinit 

}class father

public static int val = 100;

// public static string str = "string";

}class child extends father

}class constant

public static final string hello = "hello";

}

見證奇蹟的時刻到了!!!程式輸出為:

father init!

100hello

這不科學啊!!!**中呼叫了

system.out.println(child.val);

可是沒有竟然沒有對child類進行初始化。這是因為val為靜態字段,只有直接定義這個欄位的類才會被初始化,故通過子類來引用父類靜態欄位val,只會觸發father類的初始化,而不會觸發child類的初始化,so 就沒有child類的事。

再來,**中雖然有

father father = new father[4];

可是father類居然沒有初始化,這也是情理之中的。這句**僅僅定義了乙個father型別的一維陣列,陣列裡面什麼都沒有放!就好比我買了乙個可以容納100l的容器,而且是只能用來裝濃硫酸的容器,但是我現在還沒把濃硫酸放入容器,所以容器中什麼也沒有,即是沒有初始化。

看官接著往下瞧:

system.out.println(constant.hello);

constant類沒有直接父類,可為何還是沒能初始化constant類。大家也看見了,hello是乙個常量。常量和一般的變數不一樣,因為hello是常量,所以constant類在編譯階段通過常量優化傳播,把hello所代表的"hello"儲存到了notinit類的常量池中。說人話就是,以後notinit類對常量constant.hello的引用實際都轉化為notinit類對自身常量池的引用了。在編譯結束後,constant類和notinit類就勞燕分飛各自走了。

[size=large][color=red]一、 通過子類引用父類的靜態字段,不會導致子類初始化

二、 通過陣列定義來引用類,不會觸發該類的初始化

三、 常量在編譯階段會存入呼叫類的常量池中,本質上並沒有直接引用到定義常量的那個類,所以也不會觸發定義常量的類的初始化[/color][/size]

java 初始化載入

總之一句話,靜態 塊內容先執行,接著執行父類非靜態 塊和構造方法,然後執行子類非靜態 塊和構造方法。注意 子類的構造方法,不管這個構造方法帶不帶引數,預設的它都會先去尋找父類的不帶引數的構造方法。如果父類沒有不帶引數的構造方法,那麼子類必須用supper關鍵子來呼叫父類帶引數的構造方法,否則編譯不能...

java類的載入以及初始化順序

類的載入和初始化的了解對於我們對程式設計的理解有很大幫助,最近在看類的記載方面的問題。從網上查閱了若干文章,現總結如下 我們通過一段 來了解類載入和初始化的順序 package com.classloader.demo class insect private int p print insect....

java類的載入以及初始化順序

類的載入和初始化的了解對於我們對程式設計的理解有很大幫助,最近在看類的記載方面的問題。從網上查閱了若干文章,現總結如下 我們通過一段 來了解類載入和初始化的順序 package com.classloader.demo class insect private int p print insect....