Java深拷贝 - 错误的引用赋值

时间:2014-10-25 15:26:51

标签: java interface clone cloneable

请考虑以下代码

public class Pair implements Cloneable, Comparable<Para> {

    ...

    public Pair(String key, double value) throws Exception {
        if (value <= 0) throw new IllegalArgumentException();

        this.key = key;
        this.value = value;
    }

    ...

    @Override
    public Pair clone() throws CloneNotSupportedException {
        return (Pair) super.clone();
    }
}

public class BSTtree implements Dictionary, Cloneable {

    ...

    private class Node implements Cloneable, Comparable<Node> {
        Para elem;
        Node left = null;
        Node right = null;
        Node parent = null;

        Node () {
            this.elem = null;
        }

        Node (Pair elem) {
            this.elem = elem;
        }

        ...

        @Override
        public Node clone() throws CloneNotSupportedException {
            Node cloned = new Node();

            cloned.elem = elem.clone();
            if (left != null) cloned.left = left.clone();
            if (right != null) cloned.right = right.clone();

            return cloned;
        }
    }

    ...

    @Override
    public BSTtree clone() throws CloneNotSupportedException {
        BSTtree cloned = new BSTtree();
        cloned.root = root.clone();

        return cloned;
    }
}

我正在尝试使用Cloneable接口实现自己的BST树。我遇到问题的地方是

BSTtree alfa = new BSTtree();
...
BSTtree beta = alfa.clone();

我假设没有正确设置对树alfabeta的引用。我为什么这么认为?请看下面的

alfa.printTree(); //(VOID  1,00), (a  1,00), (b  2,00), (c  3,00), (e  5,00)
beta.printTree(); //(VOID  1,00), (a  1,00), (b  2,00), (c  3,00), (e  5,00)

beta.remove("a");

alfa.printTree(); //(VOID  1,00), (b  2,00), (c  3,00), (e  5,00)
beta.printTree(); //(VOID  1,00), (a  1,00), (b  2,00), (c  3,00), (e  5,00)

alfa.remove("e");

alfa.printTree(); //(VOID  1,00), (b  2,00), (c  3,00), (e  5,00)
beta.printTree(); //(VOID  1,00), (a  1,00), (b  2,00), (c  3,00), (e  5,00)

因此,您可以在克隆后看到从beta中移除的任何内容实际上已从alfa移除,并且从alfa移除根本不会删除。当然,在调用clone()之前alfa上的每个操作都正常工作。

这是为了学习,主要任务是实现一个有效的clone()方法,因此我不想使用任何其他方法来执行深层复制。

请告知我的错误,因为自我调试还没有帮助。

1 个答案:

答案 0 :(得分:2)

父更新似乎缺失 - 不确定这是否是唯一的问题......

    @Override
    public Node clone() throws CloneNotSupportedException {
        Node cloned = new Node();

        cloned.elem = elem.clone();
        if (left != null) {
           cloned.left = left.clone();
           cloned.left.parent = cloned;
        }
        if (right != null) {
           cloned.right = right.clone();
           cloned.right.parent = cloned;
        }

        return cloned;
    }

P.S。我认为另一个问题是Node是一个非静态内部类。所以它总是有一个隐含的指向它在中创建的树的指针。如果在Node.clone中调用新的Node(),则它位于原始树的范围内,因此它仍将指向原始树,但它必须是新树的内部类。在内部类声明中添加static将突出显示问题。

您可能希望将其转换为静态内部类并添加一个指向树的显式指针(如果您需要它 - 一些访问root的Node方法看起来应该是BSTtree方法)。