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 java
類在執行以前會執行三個步驟:優化
1.類的加載:查找並加載類的二進制數據,把對應的class文件加載到內存spa
2.鏈接code
2.1. 驗證:確保被加載的類的正確性(主要防止噁心的class文件被加載)blog
2.2. 準備:爲類的靜態變量分配內存,並將其初始化爲默認值接口
2.3. 解析:把類中的符合引用轉換爲直接引用內存
3.初始化:爲類的靜態變量賦予正確的初始值get
發現其中步驟2.2和3提到了關鍵字靜態變量,重點關注這兩步,2.2的結果會致使爲靜態變量編譯器
person,count1,count2分配內存並賦值(默認值)虛擬機
person=null;
count1=count2=0
到步驟3,初始化時會爲靜態變量賦予正確的值,那麼何時纔會進行初始化呢?
全部的java虛擬機實現必須在每個類或接口被java程序「首次主動使用」時才初始化
java對類的使用方式分爲:主動使用,被動使用
主動使用有六種:(除這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