Java中的拷貝可以分為深拷貝(Deep Copy)、淺拷貝(Shallow Copy)和引用拷貝(Reference Copy)。它們之間的區(qū)別如下:
淺拷貝:
只復制對象本身,而不復制對象包含的子對象。新舊對象之間共享子對象的引用,即新對象和原始對象中的子對象指向同一個內存地址。
淺拷貝:使用clone()方法或者Object類的copy()方法。
深拷貝:
不僅復制對象本身,還要復制對象包含的所有子對象。新對象和原始對象所包含的子對象是相互獨立的。
深拷貝:可以通過序列化和反序列化、遞歸遍歷等方式來實現(xiàn)。
引用拷貝:
只復制對象的引用,而不復制對象本身。新舊對象之間共享同一個對象實例,即它們的引用指向同一個內存地址。
引用拷貝:直接將對象的引用賦值給另一個變量即可。
例如,以下代碼演示了引用拷貝和淺拷貝的區(qū)別:
class Person {
public String name;
public int age;
}
public class CopyDemo {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "Alice";
p1.age = 20;
Person p2 = p1; // 引用拷貝
System.out.println(p1 == p2); // true, 引用相等
System.out.println(p1.name == p2.name); // true, 字符串常量池中的引用相同
System.out.println(p1.age == p2.age); // true, 基本數(shù)據(jù)類型的值相同
Person p3 = (Person)p1.clone(); // 淺拷貝
System.out.println(p1 == p3); // false, 引用不相等
System.out.println(p1.name == p3.name); // true, 字符串常量池中的引用相同
System.out.println(p1.age == p3.age); // true, 基本數(shù)據(jù)類型的值相同
}
}
在上面的代碼中,p1和p2是兩個對象的引用,它們指向同一個對象實例。在使用引用拷貝時,p2和p1共享同一個對象實例,所以它們的屬性值相等,并且兩個引用也是相等的。
而當使用淺拷貝時,p3是通過調用p1的clone()方法來復制p1的對象的。由于這種方式只是復制了對象本身,而沒有復制對象包含的子對象,所以p1和p3引用不同的對象實例。但由于name屬性的值是字符串常量,字符串常量池中只有一個實例,所以p1和p3的name屬性指向同一個對象。但age是一個基本數(shù)據(jù)類型,不是一個對象,所以p1和p3的age屬性值相等。
例如,以下代碼演示了深拷貝和淺拷貝的區(qū)別:
public class Address implements Cloneable {
private String name;
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
public class Person implements Cloneable {
public String name;
public int age;
private Address address;
// 省略構造函數(shù)、Getter&Setter方法
@Override
public Person clone() {
try {
Person person = (Person) super.clone();
return person;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
//測試 :
Person person1=new Person(new Address("武漢"));
Person person1Copy=person1.clone(); // true
System.out.println(person1.getAddress()==person1Copy.getAddress());
從輸出結構就可以看出, person1 的克隆對象和 person1 使用的仍然是同一個 Address 對象。
深拷貝
這里我們簡單對 Person 類的 clone() 方法進行修改,連帶著要把 Person 對象內部的 Address 對象一起復制。文章來源:http://www.zghlxwxcb.cn/news/detail-410421.html
@Override
public Person clone(){
try{
Person person=(Person)super.clone();
person.setAddress(person.getAddress().clone());
return person;
}catch(CloneNotSupportedException e){
throw new AssertionError();
}
}
測試 :
Person person1 = new Person(new Address("武漢"));
Person person1Copy = person1.clone(); // false
System.out.println(person1.getAddress() == person1Copy.getAddress());
從輸出結構就可以看出,雖然 person1 的克隆對象和 person1 包含的 Address 對象已經(jīng)是不同的了。文章來源地址http://www.zghlxwxcb.cn/news/detail-410421.html
到了這里,關于Java面試必備:深拷貝、淺拷貝、引用拷貝的區(qū)別的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!