靜態與單例

首先明確的是兩個都是線程安全的,兩者間最大的區別就是單例可以實現接口  
(Ps: 或者繼承基類,雖然這種方式很少見),所以你可以當成一個問題的兩種不同實現方式。
實際上,首先Singleton是對象(實例),
而用static修飾class的時候是方法集合,其次單例是一種設計思想。 


1. 首先明確一下,靜態成員並不是什麼程序加載時創建並初始化的,而是類加載時進行。
類的加載是第一次真正用到它的時候(拿類new實例或調用它的靜態方法)進行的,
而這個加載過程需要將 class 文件中構成類的靜態和實例方法等類的成員的字節碼指令一同加載到內存中,
而後要爲靜態域分配存儲空間並使用靜態塊對其進行初始化(如果有的話)。
在上面例子中,類加載後,所有成員(包括fun和staticfun)的字節碼指令均在內存中了,隨時等待着調用,
並且靜態域 s 所佔用的存儲空間也用空引用初始化好了。     
2. 從內存上來看,當第一次調用 getInstance() 方法時會創建此類的唯一實例(所謂的單例出現),
其實也可以在聲明 s 時 new 它的唯一實例,將實例化延後是爲了避免類加載後實例使用前內存的浪費。            
3. 靜態方法線程是安全的,所謂線程安不安全是指當多個線程同時操作一個對象(通過調用它的實例方法)時
是否會造成對象內部狀態的破壞,而靜態方法不是用來對實例進行操作的,所以一般不用考慮線程同步。
如果在靜態方法中讀寫文件,此時如果多個線程同時通過調用此靜態方法對文件操作肯定會造成文件內容的破壞,
但這不是線程沒同步造成的,因爲沒有對象的狀態被破壞。但可以利用線程同步機制防止上面情況的發生。     
4.從生命週期上來看,靜態方法的類會在代碼編譯的時候就被加載,靜態方法中產生的對象,
會隨着靜態方法執行完畢而釋放掉,而且執行類中的靜態方法時,不會實例化靜態方法所在的類。
如果用單例模式, 產生的那一個唯一的實例,會一直在內存中,不會被GC清除的(原因是靜態的屬性變量不會被GC清除),
除非整個應用退出了JVM (所以實際應用中更多的是靜態方法中獲取單例)     
5. 單例模式是利用唯一的實例保存系統的狀態,提供的實例方法也是爲了對這個唯一的實例進行操作,
而靜態方法多是一些工具方法,Math 類中的靜態方法就是一個典型的例子,
如果僅僅是想不自己創建類的實例就可以調用到某些方法來完成一定的操作,那完全沒必要也不應該使用單例模式。     
6. 從執行效率上看: 靜態方法與實例方法,在加載時機和佔用內存上,靜態方法和實例方法是一樣的,
在類型第一次被使用時加載。調用的速度基本上沒有差別。 但是從日誌打印來看,
個人感覺還是靜態方法在執行效率上快一點。     
6. 靜態方法是面向過程的,而非面向對象的編程思想

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章