Java - 单例
Posted
技术标签:
【中文标题】Java - 单例【英文标题】:Java - Singleton [duplicate] 【发布时间】:2015-07-18 01:01:53 【问题描述】:我有一些关于在 Java 中实现单例模式的问题。
当我们使用克隆时,可能会有多个单例实例。有什么具体的方法可以预防吗?
如果我们使用序列化和反序列化创建另一个单例实例会有什么影响?
【问题讨论】:
如果可以创建其他实例,这不是单例。如果您需要克隆或序列化单例的 state,请使用反映其 state 的特殊对象并对其执行克隆/序列化,而不是单例本身。 不,这就是全部的想法。写单例,这样就不会发生。但是想想不要写单例。谷歌禁止他们:code.google.com/p/google-singleton-detector 【参考方案1】:1) 不要让单例可克隆,没有人会克隆它
2) 如果 Singleton 是 Serializable 并且它不使用 readResolve 来防止重复,那么在反序列化它时会得到重复,并且它不再是 Singleton。影响取决于应用逻辑
【讨论】:
【参考方案2】:有效的 Java 项目 3: 猫王是你的班级。
public class Elvis
private static final Elvis INSTANCE = new Elvis();
private Elvis() ...
public static Elvis getInstance() return INSTANCE;
public void leaveTheBuilding() ...
如果要序列化:
// readResolve method to preserve singleton property
private Object readResolve()
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE;
或者你可以使用枚举:
// Enum singleton - the preferred approach
public enum Elvis
INSTANCE;
public void leaveTheBuilding() ...
【讨论】:
【参考方案3】:我不确定你的第二点,但这回答了第一点:
public class SingletonObject
/**
* The one and only instance of this class
*/
private static SingletonObject ref;
/**
* Creates the object. Must not be called more than once.
*/
private SingletonObject()
// no code required
/**
* Returns a reference to the singleton object
* @returns The singleton object
*/
public static synchronized SingletonObject getSingletonObject()
if (ref == null)
// First call, so create it
ref = new SingletonObject();
return ref;
/**
* Prevents cloning of the object.
* @throws CloneNotSupportedException If method is called
*/
public Object clone() throws CloneNotSupportedException
throw new CloneNotSupportedException();
您可以简单地覆盖克隆方法。
注意getSingletonObject
是同步的,如果ref
等于null
并且两个线程同时调用该函数,则会阻止创建对象的实例。
【讨论】:
【参考方案4】:要添加到@Evgeniy Dorofeev 评论,我看不出有任何理由让它可克隆并期望它也是单例。无论出于何种原因,如果它实现了 Cloneable,您始终可以通过覆盖 clone() 方法来引发异常。
【讨论】:
【参考方案5】:-
当我们使用克隆时,可能会有多个 Singleton 实例。有什么具体的方法可以预防吗?
不要实现 Cloneable
接口。当你尝试调用 `clone()~ 时,你会自动得到CloneNotSupportedException
。
-
如果我们使用序列化和反序列化创建另一个单例实例会有什么影响?
是的,您可以使用序列化创建多个版本的单例类。为防止这种情况,请不要实现Serializable
接口,或者如果您想明确 阻止序列化,您可以覆盖writeObject()
以在序列化期间抛出异常。
代码:
// Double check Singleton
class Singleton implements Serializable
private void writeObject(java.io.ObjectOutputStream stream)
throws IOException
throw new IOException("Serialization is not allowed");
private static final long serialVersionUID = -6022571167467223517L;
private volatile static Singleton singletonInstance = null;
private Singleton()
public static Singleton getInstance()
if (singletonInstance == null)
synchronized (Singleton.class)
if (singletonInstance == null)
singletonInstance = new Singleton();
return singletonInstance;
【讨论】:
以上是关于Java - 单例的主要内容,如果未能解决你的问题,请参考以下文章