我正在尝试实施 clone() A上的方法 DoubleLinkedList. 。现在,问题在于,通过“公约”实施它,比创建新的更麻烦 DoubleLinkedList 并用我当前的DoubleLinkedList的所有元素填充它。

当这样做时,我没有看到任何不便吗?

这是我当前的方法:

@Override
public DoubleLinkedList<T> clone() {
    DoubleLinkedList<T> dll = new DoubleLinkedList<T>();

    for (T element : dll) {
        dll.add(element);
    }

    return dll;
}

这就是公约:

@Override
public DoubleLinkedList<T> clone() {
    try {
        DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
        //kinda complex code to copy elements
        return dll;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e.toString());
    }
}
有帮助吗?

解决方案

正如您正确指出的那样,惯例是始终致电 super.clone() 在实施的开始 clone(). 。来自 API文档 Object#clone():

按照惯例,应通过调用super.clone获得返回的对象。如果一个类及其所有超类(对象除外)遵守此公约,则X.Clone()。getClass()== x.getClass()。

您的第一次尝试(无需使用 super.clone())有以下问题:

假设我有

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(然后 IntDoubleLinkedList 不费心覆盖 clone())我运行以下代码:

IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();

会发生什么?克隆方法的方法 您的 DoubleLinkedList 将被执行,如果它不通过super.clone(),它将返回 DoubleLinkedList 反过来不能将 IntDoubleLinkedList. 一个 ClassCastException 将被扔!

那么如何 super.clone() 解决这个问题?好吧,如果每个人都坚持打来的惯例 super.clone() 在Overriden克隆方法中, Object.clone() 最终将被调用,此实施将创建适当类型的实例(IntDoubleLinkedList 在这种情况下)!

其他提示

正如其他人所解释的那样,如果您要覆盖 clone 您应该遵守其合同。

如果您喜欢当前的方式,只需做 DoubleLinkedList 不是 Cloneable 并将您的实现变成复制构造函数或静态工厂方法。静态工厂方法也具有为通用类型参数提供一些类型推理的额外好处。

PS LinkedList 双关联列表。

如果您通过创建新列表并添加来自源的所有元素来执行此操作,则如果您执行类似的操作:

DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");

foo.property将在两个列表中都是“新值”(相反,相同的方式;如果在L1中更改它,则会在L2中出现更改)。正确的方法是实际克隆每个元素和添加克隆以确保列表是独立的。请注意,仅当您更改元素的属性时,就会发生这种情况,而不是添加,移动,将它们从列表中删除。

编辑:刚刚意识到,由于它是一个链接列表,因此下一个/上一个元素是元素的属性,因此添加,删除,都会影响两个列表。

“惯例”的原因是致电 super.clone() 是为了确保克隆对象的最终类型与要克隆的对象匹配。例如,如果您实例化新的 DoubleLinkedList 在里面 clone() 方法,现在很好,但是以后如果一个子类未能覆盖 clone() 它最终将返回一个克隆 DoubleLinkedList 而不是自己的班级。 (如果有的话,它也将无法克隆其其他字段!因此存在更大的问题。)

从这个意义上讲,传统方法是首选,它确实很笨拙。

但是,这两个实现都有类似的问题:您并没有深入研究数据结构。克隆只是一个浅的警察。这可能不是呼叫者的期望。您需要仔细替换 DoubleLinkedList 具有该值的克隆,同样适用于其他非主要字段。

从这个意义上讲,传统方法将在这里给出错误的结果!您需要第三种方式。您的第一个方法可能只是工作,除了您需要添加 element.clone() 例如。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top