是否可以浅复制单例 class 对象?

Is it possible to shallow copy a singleton class object?

使用clone方法,是否可以得到一个class单例的多个实例?

此外,是否有必要编写 "implements Cloneable",因为我了解到所有对象都从 Object class 扩展,因此在 Object 的另一个子对象上调用 protected clone() 的子对象应该没有访问权限问题

Java-Doc 说 Object.clone():

Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.

这取决于您对 clone() 方法的实施,您会得到什么样的副本或克隆。但是 Java-Doc 进一步说:

By convention, the object returned by this method should be independent of this object (which is being cloned).

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

继续Java-文档:

The class Object does not itself implement the interface Cloneable, so calling the clone method on an object whose class is Object will result in throwing an exception at run time.

所以你必须明确地声明你的classimplements Cloneable。只要你不这样做,你的实例上就没有 public clone() 方法。但是您不会为单身人士这样做,因为这会使您的 class 设计(单身)无用。

如果你没有声明单例 class final 并用另一个 class 扩展它,它的实例将调用 super.clone() 这将抛出提到的 CloneNotSupportedException.

如果你显式声明你的单例classimplements Cloneable根据Java-Doc this:

creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

要获得正确的克隆,Cloneable 的 Java-Doc 说:

... classes that implement this interface should override Object.clone ... Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface.

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


回答问题:
可能吗?是的 - 但前提是您允许。
是故意的吗?编号

另请注意:
除了上面提到的使用反射之外,您还可以尝试绕过单例的可见性限制 class 以创建更多实例。

只有通过单例实现 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

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

首先,永远不要使用克隆。 See here

其次,clone做浅拷贝。 See here

最后,建议单例使用enum,这是VM保证的。 See here