在Java中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是对象复制时两种不同的策略,它们的主要区别在于复制的深度和对象之间的引用关系。
浅拷贝(Shallow Copy)
- 浅拷贝仅仅复制对象的引用,而不是对象本身。换句话说,它创建了一个新的对象,并将原始对象的字段值复制到新对象中。但是,如果字段是引用类型(如数组、集合或其他对象),则浅拷贝会复制这些引用,而不是引用的对象。因此,原始对象及其副本将引用相同的对象。
- 在Java中,通过实现
Cloneable
接口并重写clone()
方法或使用拷贝构造函数(copy constructor)可以实现浅拷贝。 - 如果在复制之后修改了原始对象或其引用对象,则副本可能也会受到影响,因为它们引用的是相同的对象。
深拷贝(Deep Copy)
- 深拷贝会创建一个全新的对象,并递归地复制该对象及其所有子对象。它创建新的引用对象,并将它们复制到新对象中。这样,原始对象和副本对象之间没有引用关系。
- 在Java中,实现深拷贝通常比较复杂,因为需要手动编写代码来复制对象的所有字段,包括引用类型的字段。这可能需要使用序列化和反序列化、使用第三方库(如Apache Commons Lang的SerializationUtils)或手动编写递归复制逻辑。
- 深拷贝可以确保原始对象和副本对象是完全独立的。对原始对象或其引用对象的任何修改都不会影响副本对象。
示例
下滑查看解决方法
假设我们有一个Person
类,它有一个引用类型的字段address
:
class Person implements Cloneable {
private String name;
private Address address;
// 构造函数、getter和setter方法...
@Override
protected Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone(); // 浅拷贝
return person;
}
// 假设Address类也实现了Cloneable接口并重写了clone方法
}
class Address implements Cloneable {
private String street;
private String city;
// 构造函数、getter和setter方法...
@Override
protected Address clone() throws CloneNotSupportedException {
return (Address) super.clone(); // 浅拷贝
}
}
如果直接调用Person
对象的clone()
方法进行浅拷贝,那么得到的副本和原始对象将引用相同的Address
对象。为了实现深拷贝,我们需要修改Person
类的clone()
方法,以确保它也复制address
字段:
@Override
protected Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone(); // 浅拷贝Person对象
person.address = (Address) address.clone(); // 深拷贝Address对象
return person;
}
这样,原始Person
对象和副本将引用不同的Address
对象。