关于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中的深拷贝和浅拷贝介绍