目录
- 什么是对象拷贝
- 本文描述对象拷贝分类
- 浅拷贝
- 实现说明
- 代码实现
- 深拷贝
- 实现说明
- 代码实现
- 相同点
- 区别
什么是对象拷贝
对象拷贝即将源对象复制出一个新的对象,分配新的内存。
本文描述对象拷贝分类
分为浅拷贝和深拷贝
浅拷贝
顾名思义,简单浅层拷贝,将对象所有变量的值复制一份到新对象中。在Java中有基本数据类型和引用类型(值存放的是内存地址),而浅拷贝在处理引用对象和基本数据类型一样复制值到新对象,导致新对象的引用变量值是源对象引用变量的内存地址,也就是新对象和就对象操作引用变量是同一个。潜在相互影响隐患。
实现说明
该拷贝必须实现Cloneable接口,复写Object的clone方法
若不实现Cloneable接口会报ava.lang.CloneNotSupportedException:异常,应该是一种标准,目前暂未找到合理解释
代码实现
// 引用lombok,少写get/set,toString
import lombok.Data;
@Data
public class ShallowCopyTest implements Cloneable {
private String name;
private Integer age;
private ReferenceObj referenceObj;
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
public static void main(String[] args) {
ShallowCopyTest shallowCopy1 = new ShallowCopyTest();
shallowCopy1.setAge(1);
shallowCopy1.setName("NaiNiu");
ReferenceObj referenceObj = new ReferenceObj();
referenceObj.setDesc("奶牛");
referenceObj.setStatus(1);
shallowCopy1.setReferenceObj(referenceObj);
//shallowCopy1:[ShallowCopyTest(name=NaiNiu, age=1, referenceObj=ShallowCopyTest.ReferenceObj(desc=奶牛, status=1))]
System.out.println("shallowCopy1:[" + shallowCopy1.toString() + "]");
ShallowCopyTest shallowCopy2 = (ShallowCopyTest) shallowCopy1.clone();
shallowCopy2.setName("LiMao");
shallowCopy2.setAge(2);
ReferenceObj referenceObj2 = shallowCopy2.getReferenceObj();
//修改引用变量内容
referenceObj2.setDesc("狸猫");
referenceObj2.setStatus(2);
//shallowCopy1:[ShallowCopyTest(name=NaiNiu, age=1, referenceObj=ShallowCopyTest.ReferenceObj(desc=狸猫, status=2))]
//shallowCopy2:[ShallowCopyTest(name=LiMao, age=2, referenceObj=ShallowCopyTest.ReferenceObj(desc=狸猫, status=2))]
System.out.println("shallowCopy1:[" + shallowCopy1.toString() + "]");
System.out.println("shallowCopy2:[" + shallowCopy2.toString() + "]");
}
@Data
public static class ReferenceObj implements Cloneable {
private String desc;
private Integer status;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
深拷贝
顾名思义,简单浅层拷贝更深层次拷贝,即将对象所有变量的值复制一份到新对象中,并对引用变量进行深拷贝,依次深拷贝直到拷贝完成。
实现说明
该拷贝也必须实现Cloneable接口和复写Object的clone方法,引用对象变量也要实现Cloneable接口和复写Object的clone方法才能完成深拷贝,遇到引用变量需要循环拷贝直到拷贝完成。
若不实现Cloneable接口也会报ava.lang.CloneNotSupportedException:异常
代码实现
// 引用lombok,少写get/set,toString
import lombok.Data;
@Data
public class DeepCopyTest implements Cloneable {
private String name;
private Integer age;
private ReferenceObj referenceObj;
@Override
protected Object clone() {
try {
//源对象拷贝
DeepCopyTest clone = (DeepCopyTest) super.clone();
//将引用变量进行拷贝,若内部还有引用变量需要循环拷贝直到没有,才算完成
ReferenceObj referenceObj = (ReferenceObj) this.getReferenceObj().clone();
// 赋值给新对象
clone.setReferenceObj(referenceObj);
return clone;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
public static void main(String[] args) {
DeepCopyTest deepCopy1 = new DeepCopyTest();
deepCopy1.setAge(1);
deepCopy1.setName("NaiNiu");
ReferenceObj referenceObj = new ReferenceObj();
referenceObj.setDesc("奶牛");
referenceObj.setStatus(1);
deepCopy1.setReferenceObj(referenceObj);
//deepCopy1:[DeepCopyTest(name=NaiNiu, age=1, referenceObj=DeepCopyTest.ReferenceObj(desc=奶牛, status=1))]
System.out.println("deepCopy1:[" + deepCopy1.toString() + "]");
DeepCopyTest deepCopy2 = (DeepCopyTest) deepCopy1.clone();
deepCopy2.setName("LiMao");
deepCopy2.setAge(2);
ReferenceObj referenceObj2 = deepCopy2.getReferenceObj();
//修改引用变量内容
referenceObj2.setDesc("狸猫");
referenceObj2.setStatus(2);
//deepCopy1:[DeepCopyTest(name=NaiNiu, age=1, referenceObj=DeepCopyTest.ReferenceObj(desc=奶牛, status=1))]
//deepCopy2:[DeepCopyTest(name=LiMao, age=2, referenceObj=DeepCopyTest.ReferenceObj(desc=狸猫, status=2))]
System.out.println("deepCopy1:[" + deepCopy1.toString() + "]");
System.out.println("deepCopy2:[" + deepCopy2.toString() + "]");
}
@Data
public static class ReferenceObj implements Cloneable {
private String desc;
private Integer status;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
相同点
都必须实现Cloneable接口和复写Object的clone方法
开辟新的内存供新对象存放
区别
浅拷贝只做部分拷贝,深拷贝是全量拷贝
浅拷贝实现更简单,耗时短,存在新对象和源对象引用变量相互影响隐患;深拷贝实现复杂些,耗时长