摘自Herbert Schildt关于Java的书
克隆是一种潜在的危险行为,因为它可以 导致意想不到的副作用。例如,如果是对象 被克隆包含一个名为obRef的引用变量, 然后在制作克隆时,克隆中的obRef将引用 与原始中的obRef相同的对象。 如果克隆对对象的内容进行了更改 由obRef引用,那么它也将被改变为原始对象。
因此,当克隆对象时,请执行指向该对象的引用 原始对象也被克隆,因此这些指向克隆对象?
我对此行感到困惑" ...克隆中的obRef将引用 与原始中的obRef相同的对象..."。
答案 0 :(得分:2)
考虑对原始对象的引用与原始对象中的之间的区别。
假设您有myObj
类型的对象MyClass
,其中包含名为myList的ArrayList
类型的字段。
构造此对象时,myList已使用new ArrayList()
进行初始化,现在指向VM堆中的对象。
现在假设您克隆myObj
MyClass myClone = myObj.clone();
变量myClone
指向与myObj不同的对象。它们是两个不同的对象。但是,myList
内的myObj
字段将指向堆中的同一对象,myList
中为myClone
。这是因为当您克隆时,引用按原样复制,没有new ArrayList()
在新对象中为myList
分配单独的对象。
没有任何引用会自动更改,因此对旧版myObj
的任何引用仍然指向它。在将新对象分配给其他变量之前,对新对象的唯一引用是myClone
。但myList
也是如此。所以这两个对象指向相同的ArrayList
。因此,如果其中一个添加到它,另一个看到添加的值。
通常情况下,这不是你需要的。
答案 1 :(得分:0)
让我们说,我有一个名为Another的课程如下所示:
public class Another {
int number;
String message;
// And so on.
}
另一个名为CloneMe的类重写了clone()方法,如图所示:
public class CloneMe {
int version;
Another another;
public CloneMe(int newVersion, Another obj) {
this.version = newVersion;
this.another = obj;
}
// and so on
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // You can also provide your own implementation here
}
}
现在,当您创建类 CloneMe 的对象时:
CloneMe actualObject = new CloneMe(10, new Another());
然后创建一个类另一个的实例,并将其分配给CloneMe类中的另一个。
现在,当你致电:
CloneMe clonedObject = actualObject.clone();
然后,只使用 actualObject 的现有状态创建 CloneMe 的新实例。但是,没有创建任何其他类的新实例(例如,在我们的示例中为Another),但是将相同的对象引用分配给 clonedObject 中的引用变量。这称为浅层克隆。