Cloneable接口的作用与深克隆、浅克隆的理解
文章目录
一、简介
1. 为什么需要克隆
- 使用new的方式创建一个对象,这个对象是一个全新的对象,对应的属性值都是在堆空间中的默认值,所以还需要手动的给这个对象的所有属性赋予值
- 如果想要一个新的对象保存当前对象的属性值及方法(创建当前对象的副本),就需要通过克隆方法
- 把new出来的对象的属性一个一个的赋值也是可以的,但是一来麻烦,二来,clone方法是一个native方法,速度很快
2. Cloneable接口的作用
-
Cloneable是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类创建的对象调用clone方法才能克隆成功,如果不实现这个接口,则会抛出
CloneNotSupportedException
(克隆不被支持) 异常 -
Object类中的clone方法
protected native Object clone() throws CloneNotSupportedException;
3. 如何实现克隆
- 对象的类实现Cloneable接口
- 重写Object类的clone()方法
- 在clone()方法中调用super.clone();
二、浅克隆和深克隆介绍
-
浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用类型指向的对象,即拷贝之后属性中的引用类型指向的地址没有改变,两个对象的此引用类型的属性同步变化
- 如果是String类型的话,不会同步变化,因为String类的不可变性,修改了String类型的值,会新创建一个String类型对象,对原来的没有影响
-
深克隆不仅拷贝对象本身,而且拷贝对象包含的引用类型指向的对象,即拷贝之后属性中的引用类型会指向一个新的地址,一个对象中的此引用类型的属性改变不会影响到另一个对象
三、代码演示
1. 浅克隆
- 创建Student.java
public class Student implements Cloneable{
private int age;
private String name;
//getter、setter、构造器、toString
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
- 创建School.java
public class School implements Cloneable{
private String location;
private Student student;
//getter、setter、构造器、toString
@Override
protected School clone() throws CloneNotSupportedException {
return (School) super.clone();
}
}
- 创建测试类
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Student student = new Student(22, "周杰伦");
School s1 = new School("山西", student);
School s2 = s1.clone();
System.out.println(s1 + ",s1的地址值:" + s1.hashCode() +
",s1中的Student对象的地址值:" + s1.getStudent().hashCode());
System.out.println(s2 + ",s2的地址值:" + s2.hashCode() +
",s2中的Student对象的地址值:" + s2.getStudent().hashCode());
}
}
运行结果:

2. 深克隆
- 修改School.java中的clone方法
@Override
protected School clone() throws CloneNotSupportedException {
School school = (School) super.clone();
//将school中的student对象再克隆一份
school.setStudent(school.getStudent().clone());
return school;
}
运行结果:
