【发布时间】:2014-12-18 21:10:22
【问题描述】:
我有一个类,其中包含一个集合字段(宠物)。该字段包含其他集合,这些集合又包含对象。我想创建此类对象之一的深层副本。
我读过关于使用复制构造函数的文章,这似乎比使用 Cloneable 接口更舒服。我在我的 Person 类中实现了一个,并使用了 ArrayList 的复制构造函数。不幸的是,pets ArrayList 的副本不是 deepcopy - 内容仍然引用相同的内容。只有 pets ArrayList 本身被复制。 所以构造函数 ArrayList(Collection c) 没有做我想做的事。但我也读过关于遍历集合以再次复制其内容的信息——这就是我在下面的示例中所做的。 到这里,pets ArrayList 和内容,包含不同动物的 ArrayLists 被克隆。
但是动物列表中的动物对象呢? John 和 JohnClone 有自己的宠物列表,但宠物还是一样的。如果约翰的狗奥丁发生了什么事,约翰克隆的狗仍然会受到影响。
我错过了什么?如何创建集合的真正深层副本?
public class Person {
String name;
int age;
ArrayList pets;
public Person(String name, int age, ArrayList pets) {
this.name = name;
this.age = age;
this.pets = pets;
}
public Person(Person person) {
name = person.name;
age = person.age;
// pets = ArrayList(person.pets) didn't copy its contents
ArrayList clone = new ArrayList();
for (Object list : person.pets) {
clone.add(new ArrayList((ArrayList) list));
}
pets = clone;
}
public static void main(String[] args) throws Exception {
ArrayList dogs = new ArrayList();
dogs.add(new Dog("Odin"));
dogs.add(new Dog("Hachiko"));
ArrayList cats = new ArrayList();
cats.add(new Cat("Whisky"));
ArrayList johnsPets = new ArrayList();
johnsPets.add(dogs);
johnsPets.add(cats);
Person john = new Person("John Doe", 33, johnsPets);
Person johnClone = new Person(john);
}
我将 Person 的字段保留为默认值,并且没有在集合中使用泛型以避免不必要地膨胀这个简短的示例。
【问题讨论】:
-
显然,您必须手动确保您克隆一直向下。
标签: java copy clone copy-constructor deep-copy