標籤:
package init;class Person { private static Person person = new Person(); public static int count2 = 5; public static int count1; private Person() { count1++; count2++; } public static Person getInstance() { return person; }}public class Testsingleton { public static void main(String[] args) { System.out.println("count1: " + Person.count1); System.out.println("count2: " + Person.count2); }}
Output:
count1: 1
count2: 5
原因:
ClassLoader
類在執行之前會執行三個步驟:
1.類的載入:尋找並載入類的位元據,把對應的class檔案載入到記憶體
2.串連
2.1. 驗證:確保被載入的類的正確性(主要防止噁心的class檔案被載入)
2.2. 準備:為類的靜態變數分配記憶體,並將其初始化為預設值
2.3. 解析:把類中的符合引用轉換為直接引用
3.初始化:為類的靜態變數賦予正確的初始值
發現其中步驟2.2和3提到了關鍵字靜態變數,重點關注這兩步,2.2的結果會導致為靜態變數
person,count1,count2分配記憶體並賦值(預設值)
person=null;
count1=count2=0
到步驟3,初始化時會為靜態變數賦予正確的值,那麼什麼時候才會進行初始化呢?
所有的java虛擬機器實現必須在每一個類或介面被java程式“首次主動使用”時才初始化
java對類的使用方式分為:主動使用,被動使用
主動使用有六種:(除這6種外,其他都是被動使用)
1、建立類的執行個體
2、訪問某個類或介面的靜態變數或對該靜態變數賦值
3、調用類的靜態方法
4、反射
5、初始化類的子類
6、java虛擬機器啟動時被標註位啟動類的類
即在執行main方法時會為靜態變數賦值,如果有多個靜態變數,按照自上而下的順序(編譯器會最佳化,與代碼書寫的順序會不一致)
為person變數初始化時後count1=1;count2=1;
public static int count2 = 5;執行後,count2=5
驗證:
package init;class Person { public static int count2 = 5; private static Person person = new Person(); public static int count1; private Person() { count1++; count2++; } public static Person getInstance() { return person; }}public class Testsingleton { public static void main(String[] args) { System.out.println("count1: " + Person.count1); System.out.println("count2: " + Person.count2); }}
Output:
count1: 1
count2: 6
http://longpo.iteye.com/blog/2217113
java ClassLoader static