编程Java开发者

解释Java中shallow copy和deep copy对象之间的区别。如何实现它们,以及在什么情况下理解这种区别很重要?

用 Hintsage AI 助手通过面试

答案。

在Java中,shallow copy(浅拷贝)是指复制对象时,仅复制嵌套对象的引用,而不是对象本身。因此,对嵌套对象的更改将反映在副本和原始对象中。Deep copy(深拷贝)意味着创建所有嵌套对象的新独立副本。

浅拷贝示例(通过clone实现)

class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } // 使用 Person p1 = new Person("Ivan", new Address("Moscow")); Person p2 = (Person) p1.clone(); p2.address.city = "Petersburg"; System.out.println(p1.address.city); // 输出"Petersburg" — 浅拷贝

深拷贝示例

class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return new Address(this.city); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = (Address) address.clone(); return cloned; } }

深拷贝使得可以创建一个完全独立的对象副本。

开放性问题。

问题: 可以使用clone()方法来保证任意复杂对象的深拷贝吗?

答案: 不可以,标准的clone()只进行浅拷贝(shallow copy)。对于深拷贝,必须在所有嵌套类中重写clone()并明确克隆所有引用字段。此外,许多集合和标准类不支持深度克隆。

由于对主题细节的不了解而导致的实际错误示例。


故事

用户和他们的地址集合通过clone()方法进行克隆而没有进行深拷贝。修改一个用户的地址后,另一个用户的地址也发生了变化,因为复制的是引用。数据在数据库中互相"泄露"。


故事

在序列化复杂对象时使用了包含嵌套集合的clone(),而不是深拷贝。恢复序列化后,数据不一致,导致了NPE。


故事

在REST API中,DTO对象默认通过BeanUtils.copyProperties()进行克隆,导致同一个集合在不同客户端之间被共享。因此,用户能够看到和编辑他人的数据。