深入理解深浅拷贝
深入理解深、浅拷贝(Java)
以下是个人理解,如有不足,请进行指正和补充,感谢您的阅读。
【参考】https://cloud.tencent.com/developer/article/2158401?areaId=106001
一、什么是拷贝?
拷贝(中文对copy的音译),意思是复制。复制的话,大家应该都很清楚,这里就不作详细解释,意思就是生成一个相同的事物。
常见的拷贝有引用拷贝(赋值拷贝)、浅拷贝、深拷贝。
二、引用拷贝
引用变量的地址,进行复制。可以理解为浅拷贝。
public static void main(String[] args) {
int a = 1;
int b = a; //引用拷贝,引用a的地址拷贝b。
}
三、深拷贝和浅拷贝
为了便于理解深拷贝和浅拷贝,这里先声明两个对象Student和Teacher
Student类
class Student implements Cloneable {
private String name;
private int age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Teacher类
class Teacher implements Cloneable {
private String name;
private int age;
public Teacher(String name, int age) {
this.name = name; this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
3.1浅拷贝
仅复制当前所拷贝对象的引用地址,利用地址赋值。不包含当前所拷贝对象会引用的其他对象(称之为B),新拷贝的对象会和所拷贝的对象共享B,当B发生变化时可能会引起冲突。
public class QuoteCopy {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.setName("张三");
teacher.setAge(38);
Student student1 = new Student();
student1.setName("小明");
student1.setAge(14);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone(); //浅拷贝
System.out.println("拷贝后");
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge());
// 修改老师的信息
System.out.println("修改老师的信息后");
teacher.setName("王五");
System.out.println("student1的teacher为: " + student1.getTeacher().getName());
System.out.println("student2的teacher为: " + student2.getTeacher().getName()); }
}
}
输出结果:
拷贝后
小明
14
张三
38
修改老师的信息后
student1的teacher为:张三
student2的teacher为:张三
3.2深拷贝:
复制当前所拷贝对象所包含的所有引用对象和值,生成新的地址,与原始对象独立,彼此不受影响。深拷贝相比于浅拷贝速度较慢并且花销较大。
public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher(); teacher.setName("张三");
teacher.setAge(38);
Student student1 = new Student();
student1.setName("苏大");
student1.setAge(18);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println("-------------拷贝后-------------");
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge());
System.out.println("-------------修改老师的信息后-------------");
// 修改老师的信息
teacher.setName("小王");
System.out.println("student1的teacher为: " + student1.getTeacher().getName());
System.out.println("student2的teacher为: " + student2.getTeacher().getName());
}
}
class Teacher implements Cloneable {
private String name; private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable {
private String name; private int age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Object clone() throws CloneNotSupportedException {
// 浅复制时:
// Object object = super.clone();
// return object;
// 改为深复制:
Student student = (Student) super.clone();
// 本来是浅复制,现在将Teacher对象复制一份并重新set进来
student.setTeacher((Teacher) student.getTeacher().clone());
return student; }
}
输出结果:
-------------拷贝后-------------
苏大
18
张三
38
-------------修改老师的信息后-------------
student1的teacher为: 张三
student2的teacher为: 小王