使用 clone 方法,我们可以得到许多单例类的实例吗?
此外,是否有必要编写“实现 Cloneable”,因为我了解到所有对象都从 Object 类扩展,因此在 Object 的另一个子级上调用 protected clone() 的子对象应该没有访问问题
使用 clone 方法,我们可以得到许多单例类的实例吗?
此外,是否有必要编写“实现 Cloneable”,因为我了解到所有对象都从 Object 类扩展,因此在 Object 的另一个子级上调用 protected clone() 的子对象应该没有访问问题
Java-Doc 说Object.clone()
:
创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类别。
这取决于您对clone()
方法的实现,您获得什么样的副本或克隆。但是Java-Doc进一步说:
按照惯例,此方法返回的对象应独立于此对象(正在克隆)。
按照这个约定,一个克隆将是以前单例实例的另一个独立实例。
继续使用 Java-Doc:
Object 类本身并没有实现接口 Cloneable,因此在类为 Object 的对象上调用 clone 方法将导致在运行时抛出异常。
所以你必须明确声明你的类implements Cloneable
. 只要您不这样做,clone()
您的实例上就没有公共方法。但是你不会对单例这样做,因为这会使你的类设计(单例)无用。
如果您没有声明单例类final
并使用另一个类扩展它,该类的实例将调用super.clone()
这将抛出提到的CloneNotSupportedException
.
如果您要根据 Java-Doc明确声明您的单例类:implements Cloneable
创建这个对象的类的一个新实例,并用这个对象的相应字段的内容来初始化它的所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。
要获得正确的克隆,Java-DocCloneable
说:
... 实现此接口的类应该覆盖 Object.clone ... 因此,不可能仅凭借实现此接口的事实来克隆对象。
所以你真的必须明确地做到这一点。
回答问题:
可能吗?是的,但只有在您允许的情况下。
是有意的吗?不。
另请注意:
除了上面提到的使用反射之外,您还可以尝试绕过单例类的可见性限制来创建更多实例。
在您通过单例实现之前不会发生这种情况Cloneable
(这是一种反模式,因为它与单例的目的相矛盾)。因此,只有当您执行以下操作时才会发生这种情况:
SomeClass.java
class SomeClass implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
单例.java
class Singleton extends SomeClass {
public static Singleton instance = new Singleton();
private Singleton() {}
}
主.java
class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Singleton singleton1 = Singleton.instance;
Singleton singleton2 = singleton1.clone();
System.out.println("singleton1 : "
+ singleton1.hashCode());
System.out.println("singleton2 : "
+ singleton2.hashCode());
}
}
输出
单例1:445884362
单例2:1793329556
即使在这种情况下,您也可以通过覆盖并抛出异常来解决此clone
问题Singleton
。