关于Java中的深复制、浅复制,网上也有很多资料解释,这里整理出来加入一些自己的想法。
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
网上资料说:
若不对clone()方法进行改写,则调用此方法得到的对象即为浅拷贝,下面我们着重谈一下深拷贝。
经验证,引用类型的类是否重写clone()都不影响浅复制。这个不是关键点。以下是完整代码,感兴趣的同学可以验证。
public class Student implements Cloneable {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
/** * 重写Object的clone方法实现深复制 * @return */
@Override
protected Object clone() {
Object o=null;
try {
o=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
get、set省略
}
public class Classroom implements Cloneable{
private int roomNum;
private String roomName;
private Student stu;
public Classroom(int roomNum, String roomName, Student stu) {
this.roomNum = roomNum;
this.roomName = roomName;
this.stu = stu;
}
@Override
protected Object clone() {
Object o=null;
try {
o=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
get、set省略
}
经测试,引用类型的类Student是否重写clone()都不影响复制的结果。
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
深复制,对Classroom中的clone()进行如下重写。此时引用对象Student必须重写方法clone();这是因为基础类中的clone方法是protect的。
protected native Object clone() throws CloneNotSupportedException;
/** * 深复制 * @return */
@Override
protected Object clone() {
Classroom classroom=null;
try {
classroom=(Classroom)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//关键代码 copy对象的引用
classroom.stu=(Student)stu.clone();
return classroom;
}
序列化也可以实现深复制,是通过IO流实现的,开销比较大。有大神写了个类直接继承就可以实现深复制。这种方法可以提高代码的复用。
参考: Java中的深拷贝(深复制)和浅拷贝(浅复制) Java的一个高性能快速深拷贝方法。Cloneable? Java中的深拷贝和浅拷贝介绍