深克隆,同时保留对可变对象的共享引用

SantiBailors

我通过clone()某个类及其组成字段的整个层次结构中实施,来深化某个类的实例clone()我放入这些类实现中,我通过调用clone()原始(this的相应字段来分配新实例的每个字段然后,我只拜访clone()主要班级。我相信这是深度克隆的一种标准方法。

下面有一个小的可运行示例。我得到的克隆是一个真正的深层副本,其中每个字段和子字段中包含的对象都是新对象,与原始实例中的对象相同。

但这意味着,如果在原始字段中ab引用了相同的对象X,则在深层克隆中,它们将不会引用相同的对象(X的克隆)。相反,它们将引用X的两个不同克隆。

因此,我想通过深度克隆对象的整个层次结构中的所有字段来深克隆对象,但是如果层次结构在多个字段中包含相同的引用,则应仅将这些字段中的一个字段深度克隆到新对象中; 其他字段将仅引用此新对象。

用简单的解决方案看似不成问题,但是我想知道是否存在某种技术,或者某些工具或库可以做到这一点。

TestClone.java

public class TestClone {

    public static void main(String[] args) throws CloneNotSupportedException {

        // Create the object to share :

        SharedObject shared = new SharedObject(1);

        // Create the object to clone, which will own two Holder instances
        // both holding a reference to *the same* object :

        MainObject original = new MainObject(new Holder(shared), new Holder(shared));

        // Show that both holders hold a reference to the same object :

        System.out.println("Original holder1 holds " + original.holder1.field.hashCode());
        System.out.println("Original holder2 holds " + original.holder2.field.hashCode());

        // Deep-clone the main object :

        MainObject cloned = (MainObject) original.clone();

        // Show that the two cloned holders now hold a reference to *different* cloned objects :

        System.err.println("Cloned   holder1 holds " + cloned.holder1.field.hashCode());
        System.err.println("Cloned   holder2 holds " + cloned.holder2.field.hashCode());

        // How to clone so that they will hold a reference to *the same* cloned object ?
    }

}

SharedObject.java

public class SharedObject implements Cloneable {

    public int n;

    public SharedObject(int n) {

        this.n = n;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        SharedObject clone = (SharedObject) super.clone();

        clone.n = this.n;

        return clone;
    }

}

Holder.java

public class Holder implements Cloneable {

    public SharedObject field;

    public Holder(SharedObject field) {

        this.field = field;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        Holder clone = (Holder) super.clone();

        clone.field = (SharedObject) this.field.clone();

        return clone;
    }

}

MainObject.java

public class MainObject implements Cloneable {

    public Holder holder1;

    public Holder holder2;

    public MainObject(Holder holder1, Holder holder2) {

        this.holder1 = holder1;

        this.holder2 = holder2;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        MainObject clone = (MainObject) super.clone();

        clone.holder1 = (Holder) this.holder1.clone();

        clone.holder2 = (Holder) this.holder2.clone();

        return clone;
    }   

}
灵魂大师

这种克隆操作没有“标准”方式。此外,我不知道有任何支持该功能的库。

您的需求实际上是在建立从原始对象到克隆对象的一对一映射(双射)。

一种技术是,一旦在根对象上调用了clone方法,则通过克隆每个对象(如果不在地图中)来首先建立这样的层次结构。然后,将引用组装到新的克隆层次结构中。

顺便说一下,该技术已经由Java中的序列化技术实现。让您的所有类都实现Serializable,然后将根对象写入ObjectOutputStream,通过管道将其传递给ObjectInputStream,然后反序列化所有对象。序列化机制可以满足您的要求。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章