今天在学习《Head First 设计模式》模板方法模式一章中,阅读到了数组的sort()
方法的源码,其中使用了clone()
对数组进行了一份复制,再对其进行排序。之前没有接触过clone()
方法,今天查阅资料,了解了Java中的浅拷贝与深拷贝的概念,简单谈谈自己的理解。
概念
- 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对主对象进行拷贝,但不会复制主对象里面的对象。里面的对象会在原来的对象和它的副本之间共享。即,若对象中的属性是基本类型,拷贝的就是基本类型的值;若对象中的属性是引用类型,则拷贝它的内存地址,故拷贝对象与被拷贝对象两者对该引用类型的修改,都会对彼此所持有的该属性有影响。
- 深拷贝:深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。即当对象和它所引用的对象一起拷贝时为深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
实现
实现了Cloneable
接口的类具有可以被拷贝的功能,同时,需要重写clone()
方法。
- 浅拷贝实现:
1
2
3
4
5
6
7
8
public Object clone() {
try {
return super.clone(); // 直接调用父类的clone()方法
} catch (CloneNotSupportedException e) {
return null;
}
} - 深拷贝实现:
1
2
3
4
5
6
7
8
9
10/**
* 假如Student类实现了Cloneable接口,且持有一个Teacher对象
*/
public Object clone() {
Student student = (Student) super.clone(); // 先进行浅拷贝拷贝所有非引用类型的属性
student.setTeacher((Teacher) student.getTeacher().clone()); // 再将所持有的引用类型(Teacher对象)进行一次浅拷贝,并赋值给拷贝对象所持有的引用类型属性
return student; // 此时返回的拷贝对象,就持有了一个具有被拷贝对象相同引用类型属性的对象,且拷贝对象持有的该对象与被拷贝对象持有的对象不是同一个对象(内存地址不同)
}