你知道實現單例的最佳方法是列舉嗎?

2021-10-09 09:29:31 字數 2163 閱讀 3290

從jdk1.5開始,可通過編寫乙個包含單個元素的列舉型別來實現單例:

public

enum singleton

}//然後就可以通過singleton.uniqueinstace.singletonoperaion來呼叫

這種方法在功能上與共有域方法相近,但它更加簡潔,無償地提供了序列化的機制,絕對防止多次例項化,即使在面對複雜的序列化或者反射攻擊時也能防止。

單元素的列舉型別是實現singleton的最佳方法。

首先來了解常用的單例模式為何能被攻擊破壞。

破壞單例模式主要有三種方式:轉殖、反射和序列化。簡單了解一下這三種方式如何破壞單例。

public

class

testsingleton

public

static

class

singleton

implements

cloneable

public

static singleton getinstance()

@override

protected object clone()

throws clonenotsupportedexception

}}

public

class

testsingleton

public

static

class

singleton

public

static singleton getinstance()

}}

public

class

testsingleton

public

static

class

singleton

implements

serializable

public

static singleton getinstance()

}}

在objectinputstream.readobject方法執行時,其內部方法readordinaryobject中執行了該語句:

obj = desc.

isinstantiable()

? desc.

newinstance()

: null;

其中desc是類描述符,也就是說,如果乙個實現了serializable/externalizable介面的類可以在執行時例項化,那麼就呼叫newinstance()方法,使用其預設構造方法反射建立新的物件例項,自然也就破壞了單例性。

要防禦序列化攻擊,就得將instance宣告為transient,且在單例中加入:

private object readresolve()

因為在readordinaryobject方法中,會通過desc.hasreadresolvemethod()檢查類中是否存在readresolve方法,若存在,則執行desc.invokereadresolve(obj)來呼叫該方法,readresolve方法會用自定義的反序列化邏輯覆蓋預設實現,因此強制它返回instance本身,從而防止產生新的例項。

protected

enum

(string name,

int ordinal)

我們通過反射獲取這個構造方法:

constructor

constructor = enumsingleton.

class

.getdeclaredconstructor

(string.

class

,int

.class

);

測試發現丟擲如下異常:

從它丟擲的異常的注釋:cannot reflectively create enum objects可看出,從jdk反射機制的內部實現就已經排除了用反射建立列舉例項的可能。

參考:

單例模式的最佳實現

在裝載該單例類的時候就會建立類例項,例項 如下所示 public class singleton public static singleton getinstance 延遲載入思想 這一思想的核心在於直到需要使用某些資源或資料時再去載入該資源或獲取該資料,這樣可以盡可能地節省使用前的記憶體空間,一...

列舉的單例構造方法

列舉類,裡面還有對應的構造方法,但是,列舉的構造方法只能私有化,類似於單例,單個列舉後面新增的引數,可以通過私有構造方法對映出去,但是必須提供相應的get方法 例如,如下 public enum demoenum public string getmsg 測試列舉構造方的類 test public ...

關於單例模式你應該知道的

使用場景 優勢 寫法 第一種 餓漢式,執行緒安全 public class singleton public static singleton getinstance 第二種 懶漢式,執行緒不安全 雖然使用了synchronized,但無法完全保證執行緒同步 public class singlet...