參考文章:【https://www.cnblogs.com/maohuidong/p/7843807.html】
前言:
在看單例模式的時候,在網上找帖子看見其中有一種(IoDH) 實現單例的方式,其中用到了靜態內部類,文章中有寫到當jvm加載外部類的時候,並沒有加載靜態內部內這和之前自己想的不一樣,特意在網上找了一些帖子總結一下。
一、學習前千的疑問:
稍微了解Java虛擬機內的加載過程的步驟,都很清楚,一個類的靜態資源、一些常量都是在類加載的時候就被加載金內存中分配空間了,所以我一開始理所當然的以為靜態內部類中的靜態變量同樣屬於靜態資源,也應該在在內加載的時候被加載,然而實際情況卻不是這樣的,帶着這個問題我上網找了幾篇博客查找原因。
二、探究的過程:
在這里我們直接上一段代碼,在這里我們分別進行三次測試來:
public class StaticClass {
public static long OUTER_DATE = System.currentTimeMillis();
static {
System.out.println("外部類靜態塊加載時間:" + System.currentTimeMillis());
}
public StaticClass() {
System.out.println("外部類構造函數時間:" + System.currentTimeMillis());
}
static class InnerStaticClass {
public static long INNER_STATIC_DATE = System.currentTimeMillis();
static{
System.out.println("靜態內部類靜態塊加載時間:" + System.currentTimeMillis());
}
}
class InnerClass {
public long INNER_DATE = 0;
public InnerClass() {
INNER_DATE = System.currentTimeMillis();
}
}
}
1、當外部內靜態變量被調用
public static void main(String[] args) {
StaticClass outer = new StaticClass();
System.out.println("外部類靜態變量加載時間:" + outer.OUTER_DATE);
}
打印結果:
外部類靜態塊加載時間:1556088212487
外部類構造函數時間:1556088212487
外部類靜態變量加載時間:1556088212487
從控制台打印的結果我們可以看到:
外部靜態變量調用時,外部內進行了加載(注:靜態代碼塊在類被加載時執行)並且執行了初始化操作(注:構造方法被調用),而靜態內部類並沒有被加載(注:靜態內部類中的靜態代碼塊沒有執行),且類的加載順序必定會在初始化的前面,所有看到先執行了靜態代碼塊中的代碼,其次執行了構造方法中的代碼,完成上面兩部后最后才打印出了靜態變量
2、非靜態內部類變量調用時:
public static void main(String[] args) { StaticClass outer = new StaticClass(); System.out.println("非靜態內部類加載時間"+outer.new InnerClass().INNER_DATE); }
打印結果:
外部類靜態塊加載時間:1556088682706 外部類構造函數時間:1556088682706 非靜態內部類加載時間1556088682707
從控制台打印的結果我們可以看到:
非靜態內部類變量被調用時的執行結果和外部靜態變量被調用的結果一樣,並且靜態內部類也沒有被加載,出現這種情況也在預料之中,因為非靜態內部類的初始化不許依賴於外部類,如果想實例化一個非靜態內部類,則必須先實例化外部類,所以我們就看到了上面的結果
3、靜態內部類中的變量被調用時:
public static void main(String[] args) { System.out.println("靜態內部類加載時間:"+InnerStaticClass.INNER_STATIC_DATE); }
測試結果:
外部類靜態塊加載時間:1556089480349
靜態內部類靜態塊加載時間:1556089480352
靜態內部類加載時間:1556089480352
從控制台打印的結果我們可以看到:
靜態內部類的變量被調用時,我們可以看出外部類進行了加載(注:外部類中的靜態代碼塊中的代碼執行了),但是並沒有被初始化(注:外部類的構造方法並沒有執行),且靜態內部類也完成了加載
三、得出結論:
有上面我們進行的測試可以得出結論,靜態內部類和非靜態內部類一樣,都不會因為外部內的加載而加載,同時靜態內部類的加載不需要依附外部類,在使用時才加載,不過在加載靜態內部類的過程中也會加載外部類