1.主要区别
深拷贝和浅拷贝是在复制对象或数据结构时所使用的两种不同的拷贝方式,它们的区别在于拷贝程度和对原始对象内部结构的影响。
1.1浅拷贝
(1)浅拷贝创建一个新的对象,但是只复制原始对象的基本数据类型的字段或引用地址,而不复制引用指向的对象。这意味着新对象和原始对象中的引用指向相同的对象。
(2)如果原始对象中的字段是基本数据类型,那么这些字段会被复制到新对象中,而如果字段是引用类型,则新对象和原始对象对应字段将引用同一个对象
(3)因此,对新对象所做的修改可能会影响原始对象,因为他们共享相同的引用。
1.2深拷贝
(1)深拷贝创建一个新的对象,并且递归地复制原始对象的所有字段和引用指向的对象,而不仅仅是复制引用本身
(2)深拷贝会递归复制整个数据结构,包括对象内部的对象,确保新对象和原始对象之间的所有关系都是独立的
(3)这意味着新对象所做的修改不会影响原始对象,因为它们拥有彼此独立的副本
2.浅拷贝示例代码
浅拷贝的示例代码如下,我们这里实现了 Cloneable 接口,并重写了 clone() 方法。clone() 方法的实现很简单,直接调用的是父类 Object 的 clone() 方法。
class Address { private String city; public Address(String city) { this.city = city; } public String getCity() { return city; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { private Address address; public Person(Address address) { this.address = address; } public Address getAddress() { return address; } @Override protected Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } }
在上面的代码中,Address 类实现了 Cloneable 接口,并重写了 clone() 方法,而 Person 类也实现了 Cloneable 接口并重写了 clone() 方法。
在 Address 类的 clone() 方法中,直接调用了父类 Object 的 clone() 方法。
在 Person 类的 clone() 方法中,也直接调用了父类 Object 的 clone() 方法。
接下来我们进行测试,测试代码如下:
public class Main { public static void main(String[] args) { try { Person person1 = new Person(new Address("武汉")); Person person1Copy = person1.clone(); // true System.out.println(person1.getAddress() == person1Copy.getAddress()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
在这个测试中,我们期望输出 true,因为我们实现的是浅拷贝,所以新的 Person 对象和原始的 Person 对象引用的是相同的地址对象。
3. 深拷贝示例代码
这里我们简单对 Person 类的 clone() 方法进行修改,连带着要把 Person 对象内部的 Address 对象一起复制
class Person implements Cloneable { private Address address; public Person(Address address) { this.address = address; } public Address getAddress() { return address; } @Override protected Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } } class Person implements Cloneable { private Address address; public Person(Address address) { this.address = address; } public Address getAddress() { return address; } @Override protected Person clone() throws CloneNotSupportedException { Person person = (Person) super.clone(); person.address = (Address) this.address.clone(); return person; } }
在这个修改后的 clone() 方法中,我们首先调用了父类的 clone() 方法创建了一个新的 Person 对象,然后将当前对象的 address 成员变量也进行了克隆,并将克隆后的地址对象赋给新创建的 Person 对象。
接下来,我们来测试一下深拷贝的效果:
public class Main { public static void main(String[] args) { try { Person person1 = new Person(new Address("武汉")); Person person1Copy = person1.clone(); // false System.out.println(person1.getAddress() == person1Copy.getAddress()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
在这个测试中,我们期望输出 false,因为我们实现了深拷贝,所以新的 Person 对象和原始的 Person 对象引用的是不同的地址对象。