深拷貝和淺拷貝是復制對象時的兩種不同方式,它們之間的區別在于它們如何處理對象的引用類型成員。
淺拷貝(Shallow Copy)
淺拷貝是指創建一個新對象,這個新對象是對原對象的字段的一個精確副本。對于字段中的基本數據類型,淺拷貝會復制其值;但對于引用數據類型(如對象、數組),淺拷貝僅復制引用,即新對象的引用字段指向原對象中相同的對象。
特點
- 基本數據類型:復制值。
- 引用數據類型:復制引用,指向相同的內存地址。
示例
class Address {String city;Address(String city) {this.city = city;}
}class Person implements Cloneable {String name;int age;Address address;Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}// 實現淺拷貝@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class Main {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("John", 30, address);Person person2 = (Person) person1.clone();System.out.println(person1.address.city); // 輸出: New YorkSystem.out.println(person2.address.city); // 輸出: New Yorkperson2.address.city = "San Francisco";System.out.println(person1.address.city); // 輸出: San FranciscoSystem.out.println(person2.address.city); // 輸出: San Francisco}
}
在上面的示例中,person2
是通過淺拷貝創建的,因此它和person1
共享同一個Address
對象。當我們修改person2
的address
的city
時,person1
的address
的city
也會被修改。
深拷貝(Deep Copy)
深拷貝是指創建一個新對象,同時遞歸地復制所有引用類型的成員對象,確保新對象的每一個引用類型成員都有自己的獨立副本。
特點
- 基本數據類型:復制值。
- 引用數據類型:復制引用所指向的對象,創建獨立的副本。
示例
class Address implements Cloneable {String city;Address(String city) {this.city = city;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class Person implements Cloneable {String name;int age;Address address;Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}// 實現深拷貝@Overrideprotected Object clone() throws CloneNotSupportedException {Person cloned = (Person) super.clone();cloned.address = (Address) address.clone();return cloned;}
}public class Main {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("John", 30, address);Person person2 = (Person) person1.clone();System.out.println(person1.address.city); // 輸出: New YorkSystem.out.println(person2.address.city); // 輸出: New Yorkperson2.address.city = "San Francisco";System.out.println(person1.address.city); // 輸出: New YorkSystem.out.println(person2.address.city); // 輸出: San Francisco}
}
在上面的示例中,person2
是通過深拷貝創建的,它和person1
有自己的獨立Address
對象。當我們修改person2
的address
的city
時,person1
的address
的city
不會受到影響。
主要區別
-
復制內容:
- 淺拷貝:復制對象的基本類型數據和引用類型數據的引用。
- 深拷貝:復制對象的基本類型數據和引用類型數據所指向的對象。
-
內存地址:
- 淺拷貝:新對象中的引用類型成員和原對象中的引用類型成員指向同一個內存地址。
- 深拷貝:新對象中的引用類型成員和原對象中的引用類型成員指向不同的內存地址(即獨立的副本)。
-
實現復雜度:
- 淺拷貝:相對簡單,通過調用
Object
類的clone
方法可以實現。 - 深拷貝:較為復雜,需要對每個引用類型成員遞歸地調用
clone
方法,確保所有引用類型成員都得到深度復制。
- 淺拷貝:相對簡單,通過調用
適用場景
- 淺拷貝適用于對象中大部分成員是基本數據類型,或者引用類型成員是不可變對象的情況。
- 深拷貝適用于對象中包含很多引用類型成員且這些成員需要獨立的副本的情況。
理解和正確使用淺拷貝和深拷貝,對于確保程序的正確性和避免意外副作用非常重要。