如果我们将一个类实现为单例,我们将执行以下操作
class Single
{
private Single singleton;
public static Single getInstance()
{
if(null == singleton)
{
singleton = new Single();
}
return singleton;
}
//then we make the constructor private
private Single()
{
}
}
考虑到上述情况,覆盖clone()以及防止类的多个实例是一个好主意吗?
答案 0 :(得分:5)
clone()
界面中没有Cloneable
方法。如@Ivan points out所示,如果您的班级没有实施Cloneable
,那么calling Single#clone()
will throw a CloneNotSupportedException
。
也就是说,克隆是目前编写良好的Java中不常发生的事情。正如Josh Bloch在 Effective Java 中所写,第11项:
Cloneable
接口用作对象的 mixin接口(第18项) 宣传他们允许克隆。不幸的是,它没有达到这个目的。它的 主要缺陷是缺少clone
方法,Object
的克隆方法受到保护。 如果不诉诸反思(第53项),你就不能调用clone
对象上的方法仅仅因为它实现了Cloneable
。即使是反光的 调用可能会失败,因为无法保证对象具有可访问性clone
方法。尽管有这个缺陷和其他设施,该设施已广泛使用,因此它付出了代价 理解它。
...基本上,人们不会/不应该使用clone()
。这是一个设计糟糕的界面,如果你想让你的对象可以克隆,最好提供一个复制构造函数或复制工厂方法(代码从第11项中窃取):
public Yum(Yum yum); // copy constructor
public static Yum newInstance(Yum yum); // copy factory
当我谈论 Effective Java 时,有一种更好的方法来编写单例,假设你确实需要一个(这是一个很大的if! )。
从1.5版开始,实现单例的第三种方法。只是 使用一个元素创建一个枚举类型:
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
除了它之外,这种方法在功能上等同于公共领域方法 更简洁,免费提供序列化机制,并提供 铁定的保证反对多重实例化,即使面对复杂 序列化或反射攻击。虽然这种方法尚未广泛应用 采用,单元素枚举类型是实现单例的最佳方式。
答案 1 :(得分:2)
如果您不实现cloneable,则它不应该是可复制的。 附: 一个更干净的java单曲是:
class Single {
private static final Single singleton = new Single();
private Single() { }
public static Single getInstance() {
return single;
}
}
答案 2 :(得分:2)
单个对象上对clone()
的任何调用都将失败,如下所述:
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#clone%28%29
如果该课程不是Cloneable
(未指定implements Cloneable
),则会引发CloneNotSupportedException
错误。
所以不,没有必要。并且代码较少:)
答案 3 :(得分:0)
默认情况下,clone()方法被标记为受保护,但如果您的类扩展了另一个支持克隆的类,则可能违反单例的设计原则。
在这种情况下,是的,这是一个好主意:
public Object clone()
throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
答案 4 :(得分:0)