單例模式和靜態類的區別(Difference between static class and singleton pattern)
阿新 • • 發佈:2019-01-07
csdn就當自己的記事本了
這個問題的答案引用Jon Skeet 回答
首先明確的是兩個都是執行緒安全的,兩者間最大的區別就是單例可以實現介面
(Ps: 或者繼承基類,雖然這種方式很少見),所以你可以當成一個問題的兩種不同實現方式。實際上,首先Singleton是物件(例項),而用static修飾class的時候是方法集合,其次單例是一種設計思想。 看程式碼:
public class Singleton {
private static Singleton s = null;
private Singleton() { }
public static Singleton getInstance() {
if (s == null) s = new Singleton();
return s;
}
public void fun() { /* some code */ }
public static void staticfun() { /* some code */ }
public static void main(String[] args) {
Singleton.getInstance().fun();
Singleton.staticfun();
}
}
1. 首先明確一下,靜態成員並不是什麼程式載入時建立並初始化的,而是類載入時進行。類的載入是第一次真正用到它的時候(拿類new例項或呼叫它的靜態方法)進行的,而這個載入過程需要將 class 檔案中構成類的靜態和例項方法等類的成員的位元組碼指令一同載入到記憶體中,而後要為靜態域分配儲存空間並使用靜態塊對其進行初始化(如果有的話)。在上面例子中,類載入後,所有成員(包括fun和staticfun)的位元組碼指令均在記憶體中了,隨時等待著呼叫,並且靜態域 s 所佔用的儲存空間也用空引用初始化好了。 2. 從記憶體上來看,當第一次呼叫 getInstance() 方法時會建立此類的唯一例項(所謂的單例出現),其實也可以在宣告 s 時 new 它的唯一例項,將例項化延後是為了避免類載入後例項使用前記憶體的浪費。 3. 靜態方法執行緒是安全的,所謂執行緒安不安全是指當多個執行緒同時操作一個物件(通過呼叫它的例項方法)時是否會造成物件內部狀態的破壞,而靜態方法不是用來對例項進行操作的,所以一般不用考慮執行緒同步。如果在靜態方法中讀寫檔案,此時如果多個執行緒同時通過呼叫此靜態方法對檔案操作肯定會造成檔案內容的破壞,但這不是執行緒沒同步造成的,因為沒有物件的狀態被破壞。但可以利用執行緒同步機制防止上面情況的發生。 4.從生命週期上來看,靜態方法的類會在程式碼編譯的時候就被載入,靜態方法中產生的物件,會隨著靜態方法執行完畢而釋放掉,而且執行類中的靜態方法時,不會例項化靜態方法所在的類。如果用單例模式, 產生的那一個唯一的例項,會一直在記憶體中,不會被GC清除的(原因是靜態的屬性變數不會被GC清除),除非整個應用退出了JVM (所以實際應用中更多的是靜態方法中獲取單例) 5. 單例模式是利用唯一的例項儲存系統的狀態,提供的例項方法也是為了對這個唯一的例項進行操作,而靜態方法多是一些工具方法,Math 類中的靜態方法就是一個典型的例子,如果僅僅是想不自己建立類的例項就可以呼叫到某些方法來完成一定的操作,那完全沒必要也不應該使用單例模式。 6. 從執行效率上看: 靜態方法與例項方法,在載入時機和佔用記憶體上,靜態方法和例項方法是一樣的,在型別第一次被使用時載入。呼叫的速度基本上沒有差別。 但是從日誌列印來看,個人感覺還是靜態方法在執行效率上快一點。 6. 靜態方法是面向過程的,而非面向物件的程式設計思想