在Java中,对象的拷贝分为浅拷贝和深拷贝两种。浅拷贝只复制对象的引用,而深拷贝是创建一个新的对象并复制其中的所有属性值。
以下是Java中常见的浅拷贝和深拷贝的情况:
public class Person implements Cloneable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Object clone() throws CloneNotSupportedException { return super.clone(); } } Person p1 = new Person("Tom", 20); // 浅拷贝 Person p2 = p1; p2.setName("Jerry"); System.out.println(p1.getName()); // "Jerry" // 深拷贝 Person p3 = (Person) p1.clone(); p3.setName("Kate"); System.out.println(p1.getName()); // "Jerry" System.out.println(p3.getName()); // "Kate"
从上述代码中可以看出,当我们对p2进行修改时,p1的值也被改变了,这是因为p2只是p1的引用,它们指向同一个对象。而当我们对p3进行修改时,p1的值没有被改变,这是因为p3是一个新的对象,它与p1没有任何关系。
对于基本数据类型和不可变对象,比如String,浅拷贝和深拷贝没有任何区别。但对于可变对象,如数组和集合,需要格外小心,因为它们中的元素可能也是引用类型。在进行深拷贝时,我们需要递归地拷贝其中的元素。
public class MyClass implements Cloneable { private String[] arr; public MyClass(String[] arr) { this.arr = arr; } public Object clone() throws CloneNotSupportedException { MyClass copy = (MyClass) super.clone(); copy.arr = this.arr.clone(); return copy; } } String[] arr1 = { "a", "b", "c" }; MyClass obj1 = new MyClass(arr1); // 浅拷贝 MyClass obj2 = obj1; obj2.getArr()[1] = "d"; System.out.println(obj1.getArr()[1]); // "d" // 深拷贝 MyClass obj3 = (MyClass) obj1.clone(); obj3.getArr()[1] = "e"; System.out.println(obj1.getArr()[1]); // "d" System.out.println(obj3.getArr()[1]); // "e"
在进行深拷贝时,我们需要确保所有的对象都实现了Cloneable接口并正确地重写了clone方法。同时,我们也可以使用第三方库来简化深拷贝的过程,比如Apache Commons Lang库中的SerializationUtils.deepClone方法。