我们经常会用到对象的拷贝,但是但是继承Cloneable重写clone实现的只是浅拷贝,那么什么是深拷贝,什么是浅拷贝呢。
拷贝就是设计模式中原型模式的一种体现,原型模式是内存二进制流的拷贝,要比new一个对象的性能好的多的多,特别是在for循环中产生大量对象时,原型模式能更好的体现其优点。
其实从内存方面来说简单一句话,就是看有没有开辟新的内存空间用于存储拷贝的对象,浅拷贝只是拷贝一份引用,而深拷贝重新开辟堆内存存储拷贝的数据,浅拷贝对于基本类型和字符串String类型有效,具体原因这里不展开。
下面看下效果
一,继承Cloneable重写clone方法
public class Attachment implements Serializable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class YuelyLog implements Serializable,Cloneable {
private Attachment attachment;
private String name;
private String date;
@Override
protected YuelyLog clone() throws CloneNotSupportedException {
return (YuelyLog)super.clone();
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
Attachment attachment = new Attachment();
attachment.setName("wj");
YuelyLog yuelyLog = new YuelyLog();
yuelyLog.setAttachment(attachment);
yuelyLog.setDate(new Date().toString());
yuelyLog.setName("dn");
YuelyLog clone = yuelyLog.clone();
clone.getAttachment().setName("clone");
System.out.println("yelyLog:name="+(yuelyLog.getAttachment().getName()));
}
测试效果
输出:clone
说明在修改浅拷贝队形的同时原对象也发生了变化,这是一种非常危险的事情,如果处理不当,对全局性的变量或者原对象进项操作会引起大bug
其实我们拷贝一个对象就是希望他是独立的,可操作的,不会因为修改他而引起原对象发生变化。
二、下面通过序列化实现深拷贝
public class YuelyLog implements Serializable,Cloneable {
private Attachment attachment;
private String name;
private String date;
@Override
protected YuelyLog clone() throws CloneNotSupportedException {
return (YuelyLog)super.clone();
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
/**
* 使用序列化技术实现深拷贝
* @return
*/
public YuelyLog deepClone() throws IOException,ClassNotFoundException{
//将对象写入流中
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
//从流中取出
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
return (YuelyLog)objectInputStream.readObject();
}
}
继续上面的测试会发现一切如我们所期望。
在这里强调一点,当然如果你能保证在拷贝对象后,你只是对拷贝对象成员变量为基本类型和String类型进行操作,可以使用浅拷贝,像对复杂对象操作,我们一般使用深拷贝,或者对非基本类型单独实现拷贝进行修改。业务中灵活掌握。
想了解更多java相关技术,请关注公众号“JavaEE那些事”
扫描下面二维码,更多技术资料等你来拿