java浅拷贝和深拷贝
什么是拷贝
面试中经常会有面试官问什么是浅拷贝、深拷贝,但是实际编码中我们使用的并不多,在了解深拷贝、浅拷贝前,我们先大概了解一下什么是拷贝,通俗的理解就是,创建一个和已存在的对象一模一样的对象。
关于浅拷贝
浅拷贝就是将被拷贝对象的基本类型属性和String类型属性进行进行复制,引用类型属性则指向原对象的引用类型对象的地址,改变基本类型和String类型的属性值时是独立的,不会影响拷贝对象的属性,但是如果改变引用类型对象的属性时,会影响到拷贝对象的属性。
关于深拷贝
和浅拷贝相同,区别就是会将被拷贝对象的引用对象属性重新生成,而不是指向原对象引用类型对象的引用地址,所以更改引用对象时不会阴影拷贝对象的属性。
简单实现深拷贝、浅拷贝
要实现浅拷贝和深拷贝的话要实现Cloneable接口,cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException(克隆不被支持)异常。
实现浅拷贝
@Setter
@Getter
@ToString
public class FileBo implements Cloneable, Serializable {
private static final long serialVersionUID = -1013261386913302645L;
private String no;
private int count;
private FileDetailBo fileDetailBo;
@Override
public FileBo clone() {
//浅拷贝
try {
return (FileBo) super.clone();
// return CloneUtils.deepClone(this);
} catch (CloneNotSupportedException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
return new FileBo();
}
}
}
实现深拷贝
bean对象
@Setter
@Getter
@ToString
public class FileBo implements Cloneable, Serializable {
private static final long serialVersionUID = -1013261386913302645L;
private String no;
private int count;
private FileDetailBo fileDetailBo;
@Override
public FileBo clone() {
//深拷贝
try {
// return (FileBo) super.clone();
return CloneUtils.deepClone(this);
} catch (CloneNotSupportedException e) {
System.out.println(Arrays.toString(e.getStackTrace()));
return new FileBo();
}
}
}
一个深拷贝工具类
public final class CloneUtils {
private CloneUtils() {
}
;
public static <T extends Serializable> T deepClone(T t) throws CloneNotSupportedException {
// 保存对象为字节数组
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bout)) {
out.writeObject(t);
}
// 从字节数组中读取克隆对象
try (InputStream bin = new ByteArrayInputStream(bout.toByteArray())) {
ObjectInputStream in = new ObjectInputStream(bin);
return (T) in.readObject();
}
} catch (IOException | ClassNotFoundException e) {
CloneNotSupportedException cloneNotSupportedException = new CloneNotSupportedException();
e.initCause(cloneNotSupportedException)<