在最近的开发任务当中,有碰到使用深拷贝,于是就对其做了研究;那么说到深拷贝,就会有浅拷贝。那么什么是深拷贝什么是浅拷贝呢?网上给出的解释是这样的(引用:https://blog.csdn.net/qq_39207948/article/details/81067482):
同时,还有一句特别重要的:
这句话的意思在我的理解换句话来说就是:不论你是拷贝第一层级的对象属性或数组元素还是递归拷贝所有层级的对象元素都属于深拷贝;所谓的拷贝第一层级和拷贝递归所有层级他们之间的区别就在于你需要拷贝的对象属性或者数组元素涉不涉及到嵌套对象(个人理解),就比如:
public class Student{
private Integer id;
private String name;
private Integer age;
private Integer sex;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}
我如果只拷贝student类中的所有对象属性值,那么这就属于拷贝第一层级。(注意:此时student类中没有嵌套任何其他对象)
对于这种需求的拷贝我们可以使用以下的方式进行深拷贝:(当然还有其他支持拷贝第一层级的方式,在这里我只例举我用到的这个了)
/**
* 处理统计年份
* 从格式为 销量(年份),销量(年份),…… 到 销量(指定年份)
* @return
*/
private List<StoreDetailInfo> screenStatiYear(List<StoreDetailInfo> list,String year){
Pattern pattern = Pattern.compile("([0-9])*(\\()(["+year+"]{4})(\\))");
//深拷贝
List<StoreDetailInfo> filteList = (List<StoreDetailInfo>) SerializationUtils.clone((Serializable) list);
for (StoreDetailInfo info : filteList){
Matcher matcher = pattern.matcher(info.getStoreAllSaleNum());
if (matcher.find()){
StringTokenizer stringTokenizer = new StringTokenizer(matcher.group(), "(");
info.setStoreAllSaleNum(stringTokenizer.nextToken());
}else {
info.setStoreAllSaleNum("0");
}
}
return filteList;
}
至此,就已经完成了深拷贝第一层级了;但是,当该对象存在嵌套对象的话,需要同时拷贝嵌套对象中的对象属性时,我们就不能使用上面那种拷贝方式了,话不多说,先上代码:
public class Student implements Cloneable {
private Integer id;
private String name;
private Integer age;
private Integer sex;
private Address address;
@Override
public Object clone() {
Student student = null;
try {
student = (Student) super.clone(); //浅复制
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
assert student != null;
student.address = (Address) address.clone(); //深度复制
return student;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}
public class Address implements Cloneable {
private Integer id;
private String info;
@Override
public Object clone() {
Address address = null;
try {
address = (Address) super.clone(); //浅复制
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
现在我修改了一下student类,在student中嵌套了一个address类,如果此时我需要拷贝第一层级(student类)中的对象属性的同时也对第二层级(address类)的对象属性进行拷贝,那么在每个实体类中首先都需要实现Cloneable接口,然后重写clone方法,当然这样还远远不够,你在第一层级的clone方法中还需要去调用你在第二层级中重写的clone方法,这样才能实现真正递归拷贝多层级。接下来只需要调用第一层级的clone方法就够了:
Address address = new Address();
address.setId(1);
address.setInfo("上海市");
Student oldStudent = new Student();
oldStudent.setId(1);
oldStudent.setName("张三");
oldStudent.setSex(1);
oldStudent.setAge(20);
oldStudent.setAddress(address);
Student newStudent = (Student) oldStudent.clone();
以上如果有说的不对的地方或者疑点,欢迎指正,评论区交流。