天天看点

Java clone浅复制与深复制的区别1. 概述2. 浅复制clone3. 深复制clone

1. 概述

Java对象要调用 clone 进行复制,必须实现 Cloneable 接口,否则会抛出

CloneNotSupportedException

的异常。

clone 方法默认是浅复制,如果要实现深复制,那必须在clone方法调用对象成员的复制方法。

  • 浅复制:复制对象时,对象内部引用类型的成员,仍然共用内存空间。此时A对象修改这个成员的属性,B对象的该成员也会受影响。
  • 深复制:复制对象时,对象内部引用类型的成员,也会重新开辟新的空间。此时A对象和B对象完全互不干扰。

2. 浅复制clone

Grade: 班级类,实现了Cloneable接口

@Data
public class Grade implements Cloneable{
	//名称
    private String name;
    //班主任
    private Teacher headTeacher;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Grade grade = (Grade) super.clone();
        return grade;
    }
}
           

Teacher: 教师类,同样实现Cloneable接口

@Data
public class Teacher implements Cloneable{
	//姓名
    private String name;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Teacher teacher = (Teacher) super.clone();
        return teacher;
    }
}
           
  • 创建教师对象teacher,班级对象grade1
  • 从grade1复制出班级对象grade2
  • 修改grade1的名称
  • 修改grade1的班主任的姓名
public static void main(String[] args) throws CloneNotSupportedException {
        Teacher teacher = new Teacher();
        teacher.setName("张三");

        Grade grade1 = new Grade();
        grade1.setName("一班");
        grade1.setHeadTeacher(teacher);

        Grade grade2 = (Grade) grade1.clone();

        grade1.setName("小一班");
        grade1.getHeadTeacher().setName("李四");

        System.out.println(grade1);
        System.out.println(grade2);
    }
           

看下执行结果

Grade(name=小一班, headTeacher=Teacher(name=李四))
Grade(name=一班, headTeacher=Teacher(name=李四))
           
  • 班级name的修改是互不影响的。上面说了,浅复制是引用类型才公共内存空间,String是特殊的引用类型。
  • 修改grade1的班主任name,直接影响了grade2的班主任,因为headTeacher就是一个引用类型变量。

3. 深复制clone

修改上面Grade类的clone代码,复制的时候把Teacher对象也复制一份,这就是深复制。

@Override
    public Object clone() throws CloneNotSupportedException {
        Grade grade = (Grade) super.clone();
        grade.setHeadTeacher((Teacher)this.headTeacher.clone());
        return grade;
    }
           

其他代码不变,然后重新运行程序,输出如下:

Grade(name=小一班, headTeacher=Teacher(name=李四))
Grade(name=一班, headTeacher=Teacher(name=张三))
           

可以看到,headTeacher怎么修改都互不影响,深复制成功。