餓漢式單例模式測試
public class Singleton { private Singleton() {} private static final Singleton single = new Singleton(); //靜態工廠方法 public static Singleton getInstance() { return single; } }
靜態內部類實現的懶漢式單例模式spa
public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
第一種方式是餓漢式單例模式,比較容易理解的,即類在加載後就實例化了。debug
第二種方式是懶漢式單例模式,且使用了靜態內部類實現。可能不少人一開始看到的時候會以爲,使用這種方式的單例模式也是在類加載後就實例化了,其實否則,若是咱們在以上兩種單例模式的構造器中隨意加入一行打印字符串的代碼,而後加載一下以上兩個類就會發現區別。code
例如:都將構造器改成對象
private Singleton(){ System.out.println("init"); }
添加測試使用的main方法blog
public static void main(String[] args) { Singleton s = getInstance(); }
使用debug模式,在Singleton s = getInstance();一行處打上斷點,並執行main方法。因爲打了斷點,因此執行main方法後會在執行Singleton s = getInstance();前中止,但此時第一種方式的單例模式打印出了「init」字樣,而第二種方式單例模式並未打印,直到執行Singleton s = getInstance();一行代碼後纔打印「init」字樣。也就說明了第一種是餓漢式,第二種是懶漢式。字符串
關於使用靜態內部類實現的單例模式爲何是懶漢式的,其實和靜態內部類有關。get
內部類分爲對象級別(非靜態內部類)和類級別(靜態內部類),類級內部類指的是,有static修飾的成員變量的內部類。若是沒有static修飾的成員變量的內部類被稱爲對象級內部類。
it
類級內部類至關於其外部類的static成員,它的對象與外部類對象間不存在依賴關係,相互獨立,所以可直接建立。而對象級內部類的實例,是必須綁定在外部對象實例上的。class
類級內部類只有在第一次被使用的時候才被會裝載。