1、定义
深拷贝:
在Java中,深拷贝(Deep Copy)是指创建一个新对象,并将原始对象中的所有字段及其引用的对象都复制一份到新对象中,即使这些引用的对象也会被复制,而不是简单地复制引用。这意味着原始对象及其所有嵌套对象的状态在内存中存在两个独立的拷贝,彼此之间互不影响。
如果你没有看懂,换一个说法:用生活中例子来解释。
假设你有一本笔记本,里面记录着你去过的城市和你在每个城市的见闻。这个笔记本就代表了一个对象。现在,你要把这个笔记本的内容复制一份,但是不仅仅是复制内容,而是要把每个城市的见闻都重新写一遍到一个新的笔记本上,这样新的笔记本就和原来的完全独立,互不影响。这就是深拷贝的概念。
深拷贝图例:
浅拷贝:
在Java中,浅拷贝(Shallow Copy)是指创建一个新对象,然后将原始对象中的所有字段复制到新对象中,但对于引用类型的字段,只复制引用而不复制引用指向的对象。这意味着新对象与原始对象共享同一组引用对象,而不是拥有它们的副本。
如果你没有看懂,换一个说法:用生活中例子来解释。
假设你有一个购物清单A,其中包含了物品名称和数量,例如:{“苹果”: 3, “香蕉”: 2, “橙子”: 5}。
你想要创建一个新的购物清单B,其中包含了与清单A相同的物品和数量。
通过浅拷贝,你创建了一个新的购物清单B,并将清单A中的物品名称和数量复制到了清单B中。这样,清单A和清单B中的物品名称和数量都是相同的,但它们引用的是相同的物品对象。如果你在清单A中修改了物品的数量,那么清单B中对应的物品数量也会被修改,因为它们共享同一个物品对象。
浅拷贝的图例
区别:
这里我就举例子了。
假设你有一个家庭成员名单,上面列出了你的家庭成员及其联系方式。这个名单就代表了一个对象。
现在,你要复制这个名单给你的朋友,让他也能知道你的家庭成员。这就是拷贝的行为。
浅拷贝
:你把名单复制了一份给你的朋友,但是在复制的时候,你只复制了名单上的内容,而没有复制每个家庭成员的联系方式。所以,你的朋友得到了一个新的名单,但是名单上的每个家庭成员的联系方式都指向同一个家庭成员的联系方式。如果你的朋友修改了名单上某个家庭成员的联系方式,那么这个修改也会反映在你手里的名单上,因为它们共享同一个联系方式。这就是浅拷贝的特点:共享嵌套对象。
深拷贝
:你把名单复制了一份给你的朋友,但是这次你不仅复制了名单上的内容,还逐一复制了每个家庭成员的联系方式。这样,你的朋友得到了一个全新的名单,上面的每个家庭成员的联系方式都是独立的,修改其中一个家庭成员的联系方式不会影响到原来的名单。这就是深拷贝的特点:每个嵌套对象都是独立的,互不影响。
上代码:
浅拷贝
:
import java.util.ArrayList;
import java.util.List;
class Student implements Cloneable {
private String name;
private List<String> subjects;
public Student(String name, List<String> subjects) {
this.name = name;
this.subjects = subjects;
}
// 实现浅拷贝
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public List<String> getSubjects() {
return subjects;
}
}
public class ShallowCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
List<String> subjects = new ArrayList<>();
subjects.add("java语言程序设计");
subjects.add("C++从入门到精通");
Student original = new Student("张三", subjects);
Student cloned = (Student) original.clone();
System.out.println("原对象: " + original.getName() + ", 科目: " + original.getSubjects());
System.out.println("克隆对象: " + cloned.getName() + ", 科目: " + cloned.getSubjects());
// 修改原对象的科目列表
original.getSubjects().add("php从入门到精通");
System.out.println("修改后的原对象: " + original.getName() + ", 科目: " + original.getSubjects());
System.out.println("修改后的克隆对象: " + cloned.getName() + ", 科目: " + cloned.getSubjects());
}
}
输出结果:
深拷贝
:
import java.util.ArrayList;
import java.util.List;
class Student implements Cloneable {
private String name;
private List<String> subjects;
public Student(String name, List<String> subjects) {
this.name = name;
this.subjects = subjects;
}
// 实现深拷贝
@Override
public Object clone() throws CloneNotSupportedException {
Student cloned = (Student) super.clone();
// 对于引用类型字段,进行额外的拷贝
cloned.subjects = new ArrayList<>(this.subjects);
return cloned;
}
public String getName() {
return name;
}
public List<String> getSubjects() {
return subjects;
}
}
public class DeepCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
List<String> subjects = new ArrayList<>();
subjects.add("java语言程序设计");
subjects.add("C++从入门到精通");
Student original = new Student("张三", subjects);
Student cloned = (Student) original.clone();
System.out.println("原对象: " + original.getName() + ", 科目: " + original.getSubjects());
System.out.println("克隆对象: " + cloned.getName() + ", 科目: " + cloned.getSubjects());
// 修改原对象的科目列表
original.getSubjects().add("php从入门到精通");
System.out.println("修改后的原对象: " + original.getName() + ", 科目: " + original.getSubjects());
System.out.println("修改后的克隆对象: " + cloned.getName() + ", 科目: " + cloned.getSubjects());
}
}
运行结果: