java克隆浅谈

80 阅读2分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。

一、克隆的概念

克隆即是简单的对象复制。 实现克隆的要求:

  1. 必须实现Cloneable接口
  2. 实现Clonealbe接口后重写clone方法,方法修饰符改为public

二、克隆的实现

(1)浅克隆的实现

@Data
public class StudentCloneA implements Cloneable{
    private String name;

    private Integer age;

    @Override
    public StudentCloneA clone() {
        try {
            return (StudentCloneA) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
public static void main(String[] args) {
    StudentCloneA studentA = new StudentCloneA();
    studentA.setName("快乐");
    studentA.setAge(1);
    StudentCloneA studentB = studentA.clone();
    System.out.println(studentA);
    System.out.println(studentB);
}

浅克隆不会克隆对象的引用,仅仅拷贝了引用类型的指向。

(2)深克隆的实现

@Data
public class ClassClone  implements Cloneable{
    //班级名字
    private String className;
    //班级编号
    private String no;

    @Override
    public ClassClone clone() {
        try {
            ClassClone clone = (ClassClone) super.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
@Data
public class StudentCloneC implements Cloneable{
    private String name;

    private Integer age;

    private ClassClone classInfo;

    @Override
    public StudentCloneC clone() {
        try {
            StudentCloneC clone = (StudentCloneC) super.clone();
            clone.setClassInfo(clone.getClassInfo().clone());
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
//深拷贝
StudentCloneC a = new StudentCloneC();
a.setName("快乐");
a.setAge(1);
ClassClone classInfo = new ClassClone();
classInfo.setClassName("1班");
classInfo.setNo("001");
a.setClassInfo(classInfo);
StudentCloneC b = a.clone();
System.out.println(a);
System.out.println(b);
System.out.println(a.getClassInfo()==b.getClassInfo());
System.out.println(a.getName()==b.getName());

深拷贝是重新复制了一个引用类型的对象,可以看到A和B中的班级不是同一个。需要注意的是字符串也是引用类型,所以字符串的复制也是浅拷贝,下图可以看出a和b的name是同一内存地址,指向同一字符串对象。

image.png

三、总结

克隆的缺点:使用clone方法进行克隆时,如果不重写clone方法,那么只是浅克隆。使用clone方法实现克隆需要重写clone方法,对于对象中的嵌套对象,也需要实现clone方法。即如果嵌套的层次很深的时候,要维护克隆链。 克隆的优点:可以简单的复制对象。

开发中我们基本不会使用clone方法克隆对象,可以直接使用序列化与反序列化的方式复制对象,这种方式方便且不用维护克隆链。克隆是一种简单的创建原始对象精确副本的方法,但java内置的clone方法需要考虑的地方比较多,所以一般建议不用。