(一)
浅拷贝:是拷贝的一个引用;
比如说:对象A,对A进行浅拷贝之后,拷贝出来一个对象B,则B与A会指向同一个引用,如图所示:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class TestClone {
public static void main(String[] args) {
Person person1=new Person("张三",12);
Person person2=person1;
System.out.println(person1);
System.out.println(person2);
}
}
如图所示:是浅拷贝
其结果为:
根据结果可以看出,person1与person2的地址相同,说明person1与person2指向堆上的同一个对象,这就是浅拷贝
(二)
深拷贝:是重新创建了一个新对象,而不是拷贝的一个引用;
比如:对象A,对A进行深拷贝之后,会重新创建一个对象,B会指向这个新创建的对象,如图所示:
如果想要深拷贝一个对象,这个类必须实现Cloneable接口,实现clone方法;
class Person implements Cloneable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestClone {
public static void main(String[] args) {
Person person1=new Person("张三",12);
System.out.println(person1);
try {
Person person3= (Person) person1.clone();
System.out.println(person3);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
其结果为:
从图可以看出:
person1和person3的地址不一样,说明,person1和person3没有指向堆上的同一个对象;这就是深拷贝;
(三)
如果对象中包含的域引用了可变的对象,那么在拷贝该对象时,要想让这个拷贝的对象和源对象完全彼此独立,那么在引用链上的每一级对象都要被显示的拷贝;
class Person implements Cloneable{
public Object[] array; //包含了一个引用类型
public int age;
public Person(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//未对引用链上的每一级对象都进行显示的拷贝
}
}
public class TestClone {
public static void main(String[] args) {
Person person1=new Person(12);
person1.array= new Object[] {1, 2};
System.out.println(person1);
System.out.println(person1.array);
try {
Person person3= (Person) person1.clone();
System.out.println(person3);
System.out.println(person3.array);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
结果为:
发现深拷贝之后,对象内部的对象是指向同一个地址的;
下面代码中:是对引用链上的每一级对象都进行显示的拷贝:
class Person implements Cloneable{
public Object[] array;
public int age;
public Person(int age) {
this.age = age;
}
@Override
protected Person clone() throws CloneNotSupportedException {
Person result= (Person) super.clone();
result.array=array.clone();//引用链上的每一级对象都被显示的拷贝
return result;
}
}
public class TestClone {
public static void main(String[] args) {
Person person1=new Person(12);
person1.array= new Object[] {1, 2};
System.out.println(person1);
System.out.println(person1.array);
try {
Person person3= (Person) person1.clone();
System.out.println(person3);
System.out.println(person3.array);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
结果为:
发现,当对该对象上的引用链上的每一级对象都进行显示的拷贝后,其内部包含的对象指向不一样的地址,拷贝的对象与源对象完全独立;
整体来说:clone的过程:拷贝出来的新对象,先分配和源对象大小相同的内存,然后再使用源原对象中对应的各个域填充新对象的域,然后将这个新对象的引用发布