一、ArrayList的Clone方法的源码
- 返回一个Object对象,所以在使用此方法的时候要强制转换。
- ArrayList的本质是维护了一个Object的数组,所以克隆也是通过数组的复制实现的,属于浅复制。
public Object clone() {
try {
@SuppressWarnings("unchecked")
ArrayList<E> v = (ArrayList<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
拓展:
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存, 所以如果其中一个对象改变了这个地址,就会影响到另一个对象。。
浅拷贝对应的就是深拷贝,深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
二、ArrayList的Clone浅复制的巧妙使用
当你需要使用remove方法移除掉集合中的对象,而非要修改集合中的对象的时候,可以选择使用。
public class CloneTest {
public static void main(String[] args) {
ArrayList<Student> list=new ArrayList<Student>();
//添加两个元素
Student stJack=new Student("Jack", 13);
Student stTom=new Student("Tom", 15);
list.add(stJack);
list.add(stTom);
//浅克隆
ArrayList<Student> listCopy=(ArrayList<Student>) list.clone();
//移除可以,修改两者都修改
listCopy.get(0).setAge(20);
listCopy.remove(1);
System.out.println(list);
System.out.println(listCopy);
/*//深克隆
ArrayList<Student> listCopy2=new ArrayList<Student>();
for (Student student : list) {
listCopy2.add(student.clone());
}
//移除和修改都不少影响
listCopy2.get(0).setAge(13);
listCopy2.remove(1);
System.out.println(list);
System.out.println(listCopy2);*/
}
}
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
protected Student clone(){
Student stuent = new Student(this.name,this.age);
return stuent;
}
}
代码解读:
remove之前的:
remove之后的:
所以移除且不修改集合中的元素,只是在List内部的数组中移除了指向元素的地址,可以放心的使用clone。如果你想要修改克隆后的集合,那么克隆前的也会被修改。那么就需要使用深复制。
三、实现List的深复制
通过实现对象类的clone方法。
public class CloneTest {
public static void main(String[] args) {
ArrayList<Student> list=new ArrayList<Student>();
//添加两个元素
Student stJack=new Student("Jack", 13);
Student stTom=new Student("Tom", 15);
list.add(stJack);
list.add(stTom);
/* //浅克隆
ArrayList<Student> listCopy=(ArrayList<Student>) list.clone();
//移除可以,修改两者都修改
listCopy.get(0).setAge(20);
listCopy.remove(1);
System.out.println(list);
System.out.println(listCopy);*/
//深克隆
ArrayList<Student> listCopy2=new ArrayList<Student>();
for (Student student : list) {
listCopy2.add(student.clone());
}
//移除和修改都不少影响
listCopy2.get(0).setAge(20);
listCopy2.remove(1);
System.out.println(list);
System.out.println(listCopy2);
}
}
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
protected Student clone(){
Student stuent = new Student(this.name,this.age);
return stuent;
}
}