靜態類和單例的區別

關於這個問題,下面是一些同仁的觀點:

觀點一:(單例
單例模式比靜態方法有很多優勢:
首先,單例可以繼承類,實現接口,而靜態類不能(可以集成類,但不能集成實例成員);
其次,單例可以被延遲初始化,靜態類一般在第一次加載是初始化;
再次,單例類可以被集成,他的方法可以被覆寫;
最後,或許最重要的是,單例類可以被用於多態而無需強迫用戶只假定唯一的實例。舉個例子,你可能在開始時只寫一個配置,但是以後你可能需要支持超過一個配置集,或者可能需要允許用戶從外部從外部文件中加載一個配置對象,或者編寫自己的。你的代碼不需要關注全局的狀態,因此你的代碼會更加靈活。

觀點二:(靜態方法

靜態方法中產生的對象,會隨着靜態方法執行完畢而釋放掉,而且執行類中的靜態方法時,不會實例化靜態方法所在的類。如果是用singleton, 產生的那一個唯一的實例,會一直在內存中,不會被GC清除的(原因是靜態的屬性變量不會被GC清除),除非整個JVM退出了。這個問題我之前也想幾天,並且自己寫代碼來做了個實驗。

觀點三:(Good!
由於DAO的初始化,會比較佔系統資源的,如果用靜態方法來取,會不斷地初始化和釋放,所以我個人認爲如果不存在比較複雜的事務管理,用singleton會比較好。個人意見,歡迎各位高手指正。  

總結:大家對這個問題都有一個共識:那就是實例化方法更多被使用和穩妥,靜態方法少使用。

有時候我們對靜態方法和實例化方法會有一些誤解。

1、大家都以爲“ 靜態方法常駐內存,實例方法不是,所以靜態方法效率高但佔內存。

事實上,他們都是一樣的,在加載時機和佔用內存上,靜態方法和實例方法是一樣的,在類型第一次被使用時加載。調用的速度基本上沒有差別。

2、大家都以爲“ 靜態方法在堆上分配內存,實例方法在堆棧上

事實上所有的方法都不可能在堆或者堆棧上分配內存,方法作爲代碼是被加載到特殊的代碼內存區域,這個內存區域是不可寫的。

方法佔不佔用更多內存,和它是不是static沒什麼關係。  
因爲字段是用來存儲每個實例對象的信息的,所以字段會佔有內存,並且因爲每個實例對象的狀態都不一致(至少不能認爲它們是一致的),所以每個實例對象的所以字段都會在內存中有一分拷貝,也因爲這樣你才能用它們來區分你現在操作的是哪個對象。  
但方法不一樣,不論有多少個實例對象,它的方法的代碼都是一樣的,所以只要有一份代碼就夠了。因此無論是static還是non-static的方法,都只存在一份代碼,也就是隻佔用一份內存空間。  
同樣的代碼,爲什麼運行起來表現卻不一樣?這就依賴於方法所用的數據了。主要有兩種數據來源,一種就是通過方法的參數傳進來,另一種就是使用class的成員變量的值……

3、大家都以爲“實例方法需要先創建實例纔可以調用,比較麻煩,靜態方法不用,比較簡單

事實上如果一個方法與他所在類的實例對象無關,那麼它就應該是靜態的,而不應該把它寫成實例方法。所以所有的實例方法都與實例有關,既然與實例有關,那麼創建實例就是必然的步驟,沒有麻煩簡單一說。

當然你完全可以把所有的實例方法都寫成靜態的,將實例作爲參數傳入即可,一般情況下可能不會出什麼問題。

從面向對象的角度上來說,在抉擇使用實例化方法或靜態方法時,應該根據是否該方法和實例化對象具有邏輯上的相關性,如果是就應該使用實例化對象 反之使用靜態方法。這只是從面向對象角度上來說的。

如果從線程安全、性能、兼容性上來看 也是選用實例化方法爲宜。

我們爲什麼要把方法區分爲:靜態方法和實例化方法 ?

如果我們繼續深入研究的話,就要脫離技術談理論了。早期的結構化編程,幾乎所有的方法都是“靜態方法”,引入實例化方法概念是面向對象概念出現以後的事情了,區分靜態方法和實例化方法不能單單從性能上去理解,創建c++,java,c#這樣面嚮對象語言的大師引入實例化方法一定不是要解決什麼性能、內存的問題,而是爲了讓開發更加模式化、面向對象化。這樣說的話,靜態方法和實例化方式的區分是爲了解決模式的問題。

拿別人一個例子說事:

比如說“人”這個類,每個人都有姓名、年齡、性別、身高等,這些屬性就應該是非靜態的,因爲每個人都的這些屬性都不相同;但人在生物學上屬於哪個門哪個綱哪個目等,這個屬性是屬於整個人類,所以就應該是靜態的——它不依賴與某個特定的人,不會有某個人是“脊椎動物門哺乳動物綱靈長目”而某個人卻是“偶蹄目”的。

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