是否可以浅拷贝单例类对象?

时间:2018-07-04 08:12:12

标签: java singleton cloning shallow-copy shallow-clone

使用clone方法,我们能否获得一个已经做成单例的类的许多实例?

此外,有必要编写“实现可克隆的实现”,因为我了解到所有对象都从Object类扩展,因此,在另一个Object子对象上调用protected clone()的子对象应该没有访问问题

3 个答案:

答案 0 :(得分:3)

Java文档说了Object.clone()

  

创建并返回此对象的副本。的确切含义   “复制”可能取决于对象的类别。

这取决于您对clone()方法的实现,您将获得哪种复制或克隆。但是Java-Doc进一步说:

  

按照惯例,此方法返回的对象应为   与此对象(正在克隆)无关。

遵循此约定,克隆将是之前为单例实例的另一个独立实例。

继续使用Java文档:

  

类Object本身并不实现Cloneable接口,因此   在类为Object的对象上调用clone方法将   导致在运行时引发异常。

因此,您必须明确地声明您的类implements Cloneable。只要您不这样做,实例上就不会有公共的clone()方法。但是您不会为单例这样做,因为这会使您的类设计(单例)无用。

如果您没有声明单例类final并将其扩展为实例将调用super.clone()的另一个类,则会抛出所提到的CloneNotSupportedException

如果您要明确地根据Java-Doc声明您的单例类implements Cloneable

  

创建此对象的类的新实例并初始化所有   其字段与相应字段的内容完全相同   该对象,似乎是通过分配;字段的内容不是   自己克隆。因此,此方法对此进行“浅表复制”   对象,而不是“深层复制”操作。

要获得正确的克隆,Cloneable的Java文档说:

  

...实现此接口的类应重写Object.clone ...因此,仅凭其实现此接口的事实就不可能克隆对象。

所以您真的必须这样做明确


回答问题:
可能吗?是的,但只有在您允许的情况下。
有意吗不。

也请注意:
除了上述提到的反射之外,您还可以尝试绕过单例类的可见性限制来创建更多实例。

答案 1 :(得分:3)

只有在您按单例实现Cloneable时,它才会发生(这是一种反模式,因为它与单例的目的相矛盾)。因此,只有在执行以下操作时才会发生这种情况:

SomeClass.java

class SomeClass implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Singleton.java

class Singleton extends SomeClass {
    public static Singleton instance = new Singleton();
    private Singleton() {}
}

Main.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()); 
    }
}    

输出

  

singleton1:445884362

     

singleton2:1793329556

即使在这种情况下,您也可以通过在clone中覆盖Singleton并引发异常来解决此问题。

答案 2 :(得分:0)

首先,切勿使用克隆。 See here

第二,克隆做浅拷贝。 See here

最后,建议将枚举用于单例,这是VM保证的。 See here