浅拷贝(shallow copy)创建一个新对象,但复制嵌套对象的引用,而不是对象本身。深拷贝(deep copy)创建一个新对象,并递归地复制所有嵌套在源对象中的对象,因此拷贝和原始对象之间没有共享引用。
何时使用:
实现示例:
// 具有嵌套对象的类示例 class Address { String city; Address(String city) { this.city = city; } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } // 浅拷贝 public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } // 深拷贝 public Person deepClone() { return new Person(this.name, new Address(this.address.city)); } }
可以通过 clone() 方法实现深拷贝吗?
回答:
不,标准方法 Object.clone() 仅实现“浅拷贝”。要获得深拷贝,需要手动克隆所有嵌套字段,或使用第三方库(例如,Apache Commons Lang)。
示例:
@Override public Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = new Address(this.address.city); // 手动深拷贝 return cloned; }
故事
在一个大型 CRM 项目中,在通过
super.clone()实现对象复制后,开发者期望拷贝能够完全独立,但在修改拷贝用户的地址时,原始地址也被更改。这个bug在发布后被发现,并导致客户数据库中的混乱。
故事
在序列化/反序列化过程中,选择标准的 Serializable 机制进行深拷贝。然而,忘记将嵌套对象的一个字段声明为 Serializable,导致在运行时出现错误(NotSerializableException)并在备份时丢失数据。
故事
在一个微服务中,使用 BeanUtils.copyProperties 库复制 DTO,但没有意识到该机制只实现浅拷贝。重构后,出现了许多不明显的bug,当嵌套集合被修改时会影响从数据库获得的原始数据。