「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。
一、克隆的概念
克隆即是简单的对象复制。 实现克隆的要求:
- 必须实现Cloneable接口
- 实现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是同一内存地址,指向同一字符串对象。
三、总结
克隆的缺点:使用clone方法进行克隆时,如果不重写clone方法,那么只是浅克隆。使用clone方法实现克隆需要重写clone方法,对于对象中的嵌套对象,也需要实现clone方法。即如果嵌套的层次很深的时候,要维护克隆链。 克隆的优点:可以简单的复制对象。
开发中我们基本不会使用clone方法克隆对象,可以直接使用序列化与反序列化的方式复制对象,这种方式方便且不用维护克隆链。克隆是一种简单的创建原始对象精确副本的方法,但java内置的clone方法需要考虑的地方比较多,所以一般建议不用。