單例模式與靜態類(一個類,全部方法爲靜態方法)是另外一個很是有趣的問題,在《Java中有關單例模式的面試問題》博文中露掉了,因爲單例模式和靜態類都具備良好的訪問性,它們之間有許多類似之處,例如,二者能夠直接使用而無須建立對象,均可提交惟一實例,在一個很是高的高度上看起來它們都爲是用於一樣的任務。因爲它們具備較多的類似性,面試官經常會問一些相似爲神馬使用單例模式替換靜態方法?你能使用靜態類替換單例模式嗎?Java中單例模式與靜態的區別有那些?等這樣的問題,爲回答這些問題,記住他們單例模式和靜態方法之間基本的區別是很是重要的,前者給你一個Object,後者僅僅提供靜態方法,因爲對像比方法具備較強的能力,能夠指導你神馬時候使用單例模式與靜態方法。java
在本文中,咱們會了解神馬Java中的神馬地方使用單例模式,神馬時候使用靜態類更好,順便說下,JDK中有幾個關於二者的例子,而且這例子很是聰明的,例如java.lang.Math是一個final類,而且其方法爲靜態方法,另外一方面java.lang.Runtime是一個單例的類。對於那些不熟悉單例模式或靜態類的人,靜態類就是一個Java類,它僅包含靜態方法,一個很是好靜態類的例子就是java.lang.Math,它包括了許多爲不一樣數據功能實現工具方法,例如sqrt(),而單例類,在整個應用生命週期內只有一個實例,例如java.lang.Runtime。
神馬時候在Java中使用靜態類替換單例
確實存在一些場景,靜態類比單例更適合,這個場景中主要的一個例子就是java.lang.Math,它不是單例的,其全部方法都是靜態方法,這裏我給出幾個場景,我以爲使用靜態類比單例模式更適合。
1) 若是你的單例不須要維護任何狀態,僅僅提供全局訪問的方法,這種狀況考慮使用靜態類,靜態方法比單例更快,由於靜態的綁定是在編譯期就進行的。可是要記住,不建議在靜態類中維護狀態信息,特別是在併發環境中,若無適當的同步措施而修改多線程併發時,會致使壞的競態條件。
若是你須要將一些工具方法集中在一塊兒時,你能夠選擇使用靜態方法,可是別的東西,要求單例訪問資源時,應該使用單例模式。
Java中單例與靜態的區別
這是回答關於單例與靜態的第二面試問題,如我早些提到過的,它們基本的區別一個表現類,一個表現方法,下面列幾條它們之間的區別。
1) 靜態類比單例具備更好的性能,由於靜態方法在編譯期綁定。
2) 再次,它們的區別是override的能力,因Java中的靜態方法是不能夠覆蓋的,這就致使其木有太多的靈活性,另外一面,你可經過繼承的方式覆蓋單例類中定義的方法。
3) 靜態類很難模擬,所以難於單例測試,單例更容易模擬,由於也比靜態類易於編寫單元測試,不論神馬單例指望神馬,你均可以傳遞模擬對象,例如構造方法或方法參數。
4) 若是你的需求中須要維護狀態信息,則單例比靜態類更適合,由於後者在維護狀態信息方面是很是可怕的,並致使狡滑的bug。
5) 若是是一個很是重的對象,單例能夠懶加載,可是靜態類沒有這樣的優點,而且很是熱切的加載。
6) 許多依賴注入的框架對單例都有良好的管理,例如Spring,使用它們很是容易。
二者之間的這些區別,有助於咱們在面對一些場景時作出選擇,下一節中瞭解神馬時候選擇單例而不是靜態類。
Java中,選擇單例而不是靜態類的優勢
單例與靜態主要的優勢是前者比後者更具備面向對象的能力,使用單例,能夠經過繼承和多態擴展基類,實現接口和更有能力提供不一樣的實現,若是咱們討論java.lang.Runtime,在Java中它是單例,調用getRuntime()方法,會基於不一樣的JVM返回不一樣的實現,但也保證了每一個JVM中實有一個實例,若是java.lang.Runtime是一個靜態類,不太可能因不一樣的JVM返回不一樣的實現。
這就是Java中單例與靜態類的區別,當你須要一個全OO能力的對象時,選擇單例,若是僅僅是將一些靜態方法預售,使用靜態類。