經過下面的例子,驗證類的啓動方式.net
class SingletonOne { private static SingletonOne singletonOne = new SingletonOne(); public static int counter1; public static int counter2 = 0; private SingletonOne() { counter1++; counter2++; } public static SingletonOne getSingletonOne() { return singletonOne; } } class SingletonTwo { public static int counter1; public static int counter2; private static SingletonTwo singletonTwo = new SingletonTwo(); private SingletonTwo() { counter1++; counter2++; } public static SingletonTwo getSingletonTwo() { return singletonTwo; } } public class TestClassLoaderOrder { public static void main(String[] args) { System.out.println("singletonOne count1 = " + SingletonOne.counter1); System.out.println("singletonOne count2 = " + SingletonOne.counter2); System.out.println("singletonTwo count1 =" + SingletonTwo.counter1); System.out.println("singletonTwo count2 =" + SingletonTwo.counter2); } }
以上代碼,SingletonOne和SingletonTwo 兩個類的代碼惟一的區別就是code
public static int counter1;blog
public static int counter2;接口
private static SingletonTwo singletonTwo = new SingletonTwo();get
兩段代碼的順序,可是就是不一樣的順序產生不一樣的結果虛擬機
singletonOne count1 = 1class
singletonOne count2 = 0變量
singletonTwo count1 =1反射
singletonTwo count2 =1方法
SingletonTwo 容易理解,下面來探討一個爲何SingletonOne 裏的count2爲何會是「0」 由文章開頭所說,訪問某個類或接口的靜態變量,或者對該靜態變量賦值就會對類進行加載,在System.out.println()裏面均訪問了類的靜態變量,因此兩個類都會進行加載。 SingletonOne 類在啓動時,會經歷,加載,鏈接,初始化的階段,鏈接的時候,也分三步,驗證,準備,解析,在之前博文有提過http://www.javashuo.com/article/p-rxjinmbo-hr.html 準備的時候,會給靜態變量初始化默認值,這時首選counter1和counter2都是給默認值0 此時
counter1 = 0;
counter2 = 0;
緊接着進入類的初始化階段,第一段代碼執行調用了構造方法兩個值均相加1
counter1 = 1;
counter2 = 1;
在下面,count1只是聲明,不會對值改變,而count2會給此變量從新初始化值爲0
counter1 = 1;
counter2 = 0;
最後得出咱們想要的結果。
SingletonTwo相同的方式來驗證,不作贅述。