首先我们知道Java的Object类中有个clone()的方法,中文名字叫做克隆,当我们一个对象调用clone()方法时, 因为该方法默认使用的是浅拷贝,首先我们看下什么是浅拷贝?
先看下面几段代码
书包类:
public class SchoolBag {
private int size;
private String color;
public SchoolBag() {
}
public SchoolBag(int size, String color) {
this.size = size;
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "SchoolBag{" +
"size=" + size +
", color='" + color + '\'' +
'}';
}
}
学生类:
public class Student implements Cloneable {
private int id;
private int age;
private String name;
private SchoolBag schoolBag;
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SchoolBag getSchoolBag() {
return schoolBag;
}
public void setSchoolBag(SchoolBag schoolBag) {
this.schoolBag = schoolBag;
}
@Override
public Student clone() {
Student student = null;
try {
student = (Student) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
", schoolBag=" + schoolBag +
'}';
}
接下来是测试类:
public static void main(String[] args) {
Student student3 = new Student(1, 13, "吴铭");
SchoolBag schoolBag3 = new SchoolBag(22, "red");
student3.setSchoolBag(schoolBag3);
System.out.println("student3:" + student3.toString());
Student student4 = student3.clone();
System.out.println("student4:" + student4.toString());
System.out.println("after clone==================>");
student3.setAge(88);
schoolBag3.setColor("black");
System.out.println("student3:" + student3.toString());
System.out.println("student4:" + student4.toString());
}
运行的结果是:
上面的代码中,首先有个书包类(有size, color),然后有个学生类(有id, age, name),学生类中引用了书包类;
测试类中,首先有一个student3对象,student3调用clone()方法 生成student4对象,然后分别输入这两个对象的属性值,发生控制台(第一行、第二行)都是一样的;
然后修改student3的age, 以及其引用的shcoolBag的color属性,然后在打印输出,有了控制台第四行、第五行的内容,我们可以发现,student3的age与student4的age不一样,student4的age没有被修改,那是因为clone() 方法只是复制了当前对象的所有基本数据类型,以及相对应的引用变量(地址),但是没有复制引用变量指向的实际对象,这就是浅拷贝;
那怎么实现是属于深拷贝呢 ?
我们需要复写clone()方法。
上述Student类中的clone方法改为如下:
@Override
public Student clone() {
Student student = null;
try {
student = (Student) super.clone();
student.setSchoolBag(schoolBag.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
SchoolBag类中实现Cloneable接口,重写clone方法,如下:
@Override
public SchoolBag clone() {
SchoolBag schoolBag = null;
try {
schoolBag = (SchoolBag) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return schoolBag;
}
然后在运行测试类代码,结果如下:
上面我们可以发现,student4的age和schoolBag都没有修改了,这就是深拷贝,不仅复制当前对象的基本数据类型和相应的引用变量,也复制引用变量指向的实际对象,会指向一个新的对象。
综上:
浅拷贝:复制了当前对象的所有基本数据类型,以及相对应的引用变量(地址),但是没有复制引用变量指向的实际对象;
深拷贝:不仅复制当前对象的基本数据类型和相应的引用变量,也复制引用变量指向的实际对象,会指向一个新的对象