深拷贝和浅拷贝是复制对象时的两种不同方式,它们之间的区别在于它们如何处理对象的引用类型成员。
浅拷贝(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
方法,确保所有引用类型成员都得到深度复制。
- 浅拷贝:相对简单,通过调用
适用场景
- 浅拷贝适用于对象中大部分成员是基本数据类型,或者引用类型成员是不可变对象的情况。
- 深拷贝适用于对象中包含很多引用类型成员且这些成员需要独立的副本的情况。
理解和正确使用浅拷贝和深拷贝,对于确保程序的正确性和避免意外副作用非常重要。