Java对象深浅拷贝详解与实例

0 下载量 81 浏览量 更新于2024-09-01 收藏 100KB PDF 举报
"这篇文档详细解释了Java中的对象拷贝,包括浅拷贝和深拷贝的概念,并通过实例展示了如何实现。" 在Java编程中,对象拷贝是一个关键概念,尤其是当你需要创建一个对象的独立副本,使得原对象和副本在后续修改时互不影响。Java的赋值操作实际上是复制对象的引用,而不是对象本身,这意味着两个引用指向同一个内存位置。例如,当我们执行`Person p2 = p1;`时,`p1`和`p2`都指向了同一个Person对象。 要实现真正的对象复制,我们需要使用克隆(clone)机制。Java的`Object`类提供了一个`clone()`方法,但是它是受保护的(`protected`),默认情况下不对外部类公开。因此,如果我们想要在自定义类中使用`clone()`,需要遵循以下步骤: 1. 实现`Cloneable`接口:这是一个标记接口,不包含任何方法。实现这个接口告诉Java你的类支持克隆。 2. 覆盖`clone()`方法:将它的访问修饰符改为`public`,以便在类的外部调用。通常,你只需调用`super.clone()`来执行默认的克隆行为。 以下是一个简单的示例,展示了一个名为`Person`的类如何实现克隆: ```java @Data public class Person implements Cloneable { private String name; private Integer age; private Address address; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这个例子中,`Person`类包含了两个基本类型(`String`和`Integer`)和一个引用类型(`Address`)。当执行`p1.clone()`时,如果`Address`对象也实现了`Cloneable`并覆盖了`clone()`方法,那么`Address`对象也会被深拷贝。然而,如果没有这样做,`Address`对象将只进行浅拷贝,意味着`p1`和`p2`的`address`字段仍然指向同一个`Address`实例。 通过以下测试用例,我们可以看到深拷贝的效果: ```java @Test public void testShallowCopy() throws Exception { Person p1 = new Person(); p1.setAge(31); p1.setName("Peter"); Person p2 = (Person) p1.clone(); System.out.println(p1 == p2); // false,表明p1和p2是不同的对象 p2.setName("Jacky"); System.out.println("p1=" + p1); // p1=Person[name=Peter,age=31] System.out.println("p2=" + p2); // p2=Person[name=Jacky,age=31] } ``` 在这个测试中,`p1`和`p2`的`name`属性被独立修改,证明了它们是相互独立的对象副本。然而,如果`Address`对象也包含可变属性,而没有被深拷贝,那么修改`p2`的`address`属性会影响到`p1`的`address`属性,这就是浅拷贝的特性。 总结来说,Java对象拷贝分为浅拷贝和深拷贝。浅拷贝只复制对象本身,而不复制其引用的对象;深拷贝则会递归地复制对象及其所有嵌套的对象。在实现克隆时,确保所有可变的嵌套对象都支持深拷贝,才能确保对象副本的真正独立。