java深度克隆
java深度克隆
版权声明:本文为CSDN博主「爪 哇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40794973/article/details/106208799
浅克隆:复制对象时仅仅复制对象本身,包括基本属性,但该对象的属性引用其他对象时,该引用对象不会被复制,即拷贝出来的对象与被拷贝出来的对象中的属性引用的对象是同一个。
深克隆:复制对象本身的同时,也复制对象包含的引用指向的对象,即修改被克隆对象的任何属性都不会影响到克隆出来的对象。
值得一提的是,上文所说的浅拷贝只会克隆基本数据属性,而不会克隆引用其他对象的属性,但String对象又不属于基本属性,这又是为什么呢?
这是因为String对象是不可修改的对象,每次修改其实都是新建一个新的对象,而不是在原有的对象上修改,所以当修改String属性时其实是新开辟一个空间存储String对象,并把引用指向该内存,而克隆出来的对象的String属性还是指向原有的内存地址,所以String对象在浅克隆中也表现得与基本属性一样。
@Data
public class Pig implements Cloneable, Serializable {
private static final long serialVersionUID = 779970270042384579L;
private String name;
private Date birthday;
public Pig(String name, Date birthday) {this.name = name;this.birthday = birthday;}
// 方法1、深拷贝——使用clone方法
//Remove this "clone" implementation; use a copy constructor or copy factory instead.
@Override
protected Pig clone() throws CloneNotSupportedException {
Pig pig = (Pig) super.clone();
//实现深度克隆要对引用类型重新克隆,如果对象中引用类型过多的话,写的代码会变多,也有可能会有遗漏
pig.birthday = (Date) pig.birthday.clone();
return pig;
}
// 2、深拷贝——通过对象的序列化实现 (推荐)
public Pig deepClone() {
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); //当前这个对象以对象流的方式输出
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return (Pig) ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
//关闭流
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e) {}
}
}
}