我认为下面的clone方法是深度克隆,因为它在复制信息之前创建了一个新对象。然而,这是一个肤浅的克隆。我想知道为什么。
class FixedVector {
public static int count;
private Object data[];
private int length = 0;
public FixedVector(int size) {
count++;
data = new Object[size];
}
public void add(Object ob) {
if (length < data.length) {
data[length++] = ob;
} else {
throw new InsufficientSpaceException();
}
}
public Object get(int index) {
if (index < length) {
return data[index];
} else {
throw new IndexOutOfBoundsException();
}
}
public Object clone() {
FixedVector c = new FixedVector(data.length);
for (int i = 0; i < length; ++i) {
c.data[i] = data[i];
}
return c;
}
public static void main(String argv[]) {
FixedVector n = new FixedVector(10);
try {
n.get(1);
} catch (InsufficientSpaceException ie) {
System.out.println("ERROR 1");
} catch (IndexOutOfBoundsException oe) {
System.out.println("ERROR 2");
}
}
}
clone()
方法是您实现的任何1。如果你想实现深度复制,那是允许的。如果你想实现浅拷贝,这也是允许的。
在这个例子中,FixedVector
的作者显式地将clone()
实现为浅拷贝。显然,代码将按照编写的方式运行……即浅层复制data
数组。
现在…如果你问在这种情况下会发生什么:
public class FixedVector implements Cloneable {
...
public Object clone() {
return super.clone();
}
}
更有趣。这里我们依靠的是"魔法"。Object.clone()
的克隆行为。但是它被定义为执行目标对象字段的浅拷贝。因此克隆将与克隆对象共享数据数组。(这不是我们想要的,在这种情况下,因此FixedVector
实现克隆,正如你的问题。)
注意"deep"one_answers";shallow"副本很有弹性。在您的示例中,实际上(至少)有3种方法可以执行复制:
Object.clone()
方式给出了一个共享的data
数组。那是"肤浅的"。副本。问题中的方法给出了不同的
data
数组,但共享元素。这是一个"深"字。副本。另一种方法是克隆数组中的元素。这将是一个"更深"的问题。副本。在您的示例中,如果可以更改
c.data[i] = data[i];
c.data[i] = data[i].clone();
但实际深度取决于元素类2如何实现
clone
。这个行为是类特有的。
1 -Object.clone()
javadoc谈论"一般意图";clone()
方法,但它明确表示允许类忽略它。然而,我想说忽略javadoc所说的内容是不明智的。
2 -这不会按原样编译。但是,如果您将Object[] data
替换为SomeClass[] data
,其中SomeClass
将clone()
声明为public
方法,则可以。