提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本文浅析浅拷贝与深拷贝的区别、拷贝与克隆之间的关系、以及浅克隆与深克隆的区别。
一、浅拷贝与深拷贝的区别
1.浅拷贝示例
public class Test {
public static void main(String[] args) {
Teacher teacher1 = new Teacher("kaidi", 20);
Teacher teacher2 = teacher1;
System.out.println(teacher1 == teacher2);
}
}
class Teacher {
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;
}
}
以上代码输出结果:true
浅拷贝只是简单地将一个对象的引用赋值给另一个变量,并没有创建一个新的对象,旧引用与新引用的值相等,指向同一个对象。
2.深拷贝示例
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher1 = new Teacher("kaidi", 20);
Teacher teacher2 = (Teacher) teacher1.clone();
System.out.println(teacher1 == teacher2);
}
}
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();
}
}
以上代码输出结果:false
由输出结果可知teacher1和teacher2两个引用的值并不相等,即指向了不同的内存地址(指向了不同的对象)。调用一个对象的克隆方法即可实现对象的深拷贝。
二、浅克隆与深克隆的区别
1.对象调用clone方法的条件
- 对象所对应的类实现 Cloneable 接口。
- 对象所对应的类重写 Object 类中的 clone() 方法,并调用super.clone()。
2.浅克隆示例
public class ShallowCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setName("kaidi");
teacher.setAge(20);
Student student1 = new Student();
student1.setName("zhangsan");
student1.setAge(10);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println(student1 == student2);
System.out.println(student1.getTeacher() == student2.getTeacher());
}
}
class Teacher{
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;
}
}
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();
}
}
以上代码输出结果:
1、false
2、true
1、student1调用clone方法克隆了另一个对象,旧引用与新引用指向不同的对象。
2、对于克隆对象的成员变量,不管是基本数据类型还是引用数据类型,都是简单地复制旧对象的值。即对于引用类型并不会创建一个新的对象,只会将旧引用的值赋值给新引用,两个引用都指向原来的对象。
3.深克隆示例
public class ShallowCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setName("kaidi");
teacher.setAge(20);
Student student1 = new Student();
student1.setName("zhangsan");
student1.setAge(10);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println(student1 == student2);
System.out.println(student1.getTeacher() == student2.getTeacher());
}
}
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 {
//深克隆
Student student = (Student) super.clone();
student.setTeacher((Teacher) this.getTeacher().clone());
return student;
}
}
以上代码输出结果:
1、false
2、false
1、student1调用clone方法克隆了另一个对象,旧引用与新引用指向不同的对象。
2、深克隆,即在对象调用super.clone方法后,继续将对象所有的引用类型都调用clone方法,并赋值给克隆对象对应的引用。这样,克隆对象对应的每个引用成员变量都指向了自己的地址空间,而不是和原对象的每个引用成员变量指向相同的地址空间了。
总结
浅拷贝只是简单的引用赋值,旧引用和新引用指向相同的地址空间;深拷贝会创建出另一个新的对象,旧引用和新引用指向不同的地址空间,可以通过调用clone方法实现。
深拷贝又包括浅克隆和深克隆。浅克隆中,克隆对象的每个引用成员变量都和原对象的每个引用成员变量指向相同的地址空间;深克隆中,克隆对象的每个引用成员变量都和原对象的每个引用成员变量指向不同的地址空间。