(一)
淺拷貝:是拷貝的一個引用;
比如說:對象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的過程:拷貝出來的新對象,先分配和源對象大小相同的內存,然後再使用源原對象中對應的各個域填充新對象的域,然後將這個新對象的引用發佈