【发布时间】:2019-01-02 02:27:13
【问题描述】:
我正在阅读 Joshua Bloch 的 Effective Java,第 2 版,第 11 项:明智地覆盖克隆。
在第 56 页,他试图解释当我们为某些类(如集合类)覆盖 clone() 时,我们必须复制它的内部。然后他给出了设计类Stack的例子:
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {...}
public void push(Object e) {...}
public Object pop() {...}
private void ensureCapacity() {...} //omitted for simplicity
}
他声称,如果我们简单地使用super.clone() 克隆Stack,则生成的 Stack 实例“将在其 size 字段中具有正确的值,但它的 elements 字段将引用与原始 Stack 实例相同的数组. 修改原来的会破坏克隆中的不变量,反之亦然。你会很快发现你的程序产生了无意义的结果或抛出了 NullPointerException。
现在看来这很公平。但他随后给出了一个“正确实现”的例子,这让我感到困惑:
@Override public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
现在这与super.clone() 有何不同?我知道,新的Stack.element 将与旧的完全不同;但是数组的“内部结构”还是一样的,不是吗?数组result.element 的实际元素仍然指向原始Object 引用。这仍然可能导致在更改原始文件时破坏克隆的不变量,反之亦然,不是吗?我错过了什么吗?
【问题讨论】:
-
你可以找到here,你说的是对的。
elements.clone()不会克隆内容。
标签: java