最近在刷Leetcode,里面经常用到ArrayList,对于ArrayList的拷贝也是弄得不是很明白。
ArrayList的拷贝方法有很多,其中大部分都是浅拷贝,例如通过构造函数方法拷贝,
1 List l2 = new ArrayList<>(l1);
或者addAll方法:
1 List l2 = new ArrayList<>();2 l2.addAll(l1);
这些都是浅拷贝,其中clone()方式有些特殊,最开始我以为通过clone()是实现深拷贝,因为我看很多题解都是用这种方式进行拷贝。但其实clone()也是浅拷贝,原因如下:
之所以题解经常用clone()或者构造方法直接进行复制,是因为做题通常是Interger或者String类型的List,Interger和String类型都是不可变类,那么只需要通过浅拷贝拷贝一层即可。
而后,我看一些文章写深拷贝方法,其中有一个比较特殊。
例如有一个Person类如下:
static classPerson implements Cloneable{intage;public Person(int age){this.age =age;}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
}
通过以下代码,可以实现深拷贝;
List l3 = new ArrayList<>();
List l4 = new ArrayList<>();for(Person person:l3)
l4.add((Person)person.clone());
但是这样的说法不准确,这样的代码只是多拷贝了一层,如果Person类改成如下,这样的拷贝就不成立了。
static class Person implementsCloneable{inta;
Age age;public Person(int a){this.a =a;}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
}
虽然完成了对Person的拷贝,改变person2的属性值不会影响到person1,但是person1和person2引用的Age对象是同一个,也就是没有实现深拷贝。
后来发现,在实际场景中,在代码逻辑层面想要完全实现深拷贝非常困难,因为难免会碰到有一些类套娃套了很多层。于是经过继续看一些文章,发现使用序列化方法可以实现深拷贝。
这段代码来自其他文章
1 public static List deepCopy(List src) throwsIOException, ClassNotFoundException {2 ByteArrayOutputStream byteOut = newByteArrayOutputStream();3 ObjectOutputStream out = newObjectOutputStream(byteOut);4 out.writeObject(src);5
6 ByteArrayInputStream byteIn = newByteArrayInputStream(byteOut.toByteArray());7 ObjectInputStream in = newObjectInputStream(byteIn);8
9 List copy_list = (List) in.readObject();10 returncopy_list;11 }
所有需要拷贝到的对象,通通要实现Serializable
static class Person implementsSerializablestatic class Age implements Serializable