我有一个类,其中包含一个收集字段(宠物)。该字段包含其他集合,这些集合再次包含对象。我想创建一个这个类的对象的深度复制。
我已经阅读过有关使用复制构造函数的内容,这看起来比使用Cloneable接口更舒服。我在Person类中实现了一个并使用了ArrayList的复制构造函数。不幸的是,宠物ArrayList的副本不是深度复制 - 内容仍然引用相同的内容。只复制了宠物ArrayList本身。 所以构造函数 ArrayList(Collection c)没有按照我的意愿去做。但我也读过关于迭代集合以再次复制其内容的内容 - 这就是我在下面的例子中所做的。 在这里克隆了宠物ArrayList和内容,包含不同动物的ArrayLists。
但动物名单中的动物物品怎么样? John和JohnClone有他们自己的宠物清单,但宠物仍然是一样的。如果John的狗Odin发生了什么事,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的字段默认值,并且没有在集合中使用泛型,这不是不必要的膨胀这个简短的例子。
答案 0 :(得分:1)
我想我会坚持使用与Suresh Sajja提到的解决方案类似的解决方案来克隆不太嵌套的对象。
否则我读到有关序列化对象以创建深层副本的信息:Deep cloning objects。 我想这些是必须使用的解决方案,因为Java没有提供这样的方法。
答案 1 :(得分:0)
以与在宠物中克隆动物名单相同的方式行事。使用Objects
的克隆构造数组列表ArrayList clone = new ArrayList();
for (Object list : person.pets) {
ArrayList objClone = new ArrayList();
for(Object obj : list){
objClone.add(obj.clone()); //you have to honour the contract of cloneable while doing this on dog, cat objects
}
clone.add(objclone);
}
pets = clone;