在项目中看到前人写的代码用到了 spring 框架的 BeanUtils.copyProperties 方法,想了解一下这个方法是深拷贝还是浅拷贝,其实这个方法内部对于基本数据类型实现了深拷贝,但对于引用类型还是浅拷贝的。
一、什么是浅拷贝和深拷贝
在 Java 中,除了基本数据类型(元类型)之外,还存在类的实例对象这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。
而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。
因此,所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对 类的实例对象 这种引用数据类型的不同操作而已。
总结来说:
- 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
- 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
二、实现深拷贝的方法
浅拷贝和深拷贝其实是相对的:
- 如果一个对象内部只有基本数据类型,那用 clone() 方法获取到的就是这个对象的深拷贝;
- 而如果其内部还有引用数据类型,那用 clone() 方法就是一次浅拷贝的操作。
那么,如何进行一个深拷贝呢?
比较常用的方案有两种:
- 序列化(serialization)这个对象,再反序列化回来,就可以得到这个新的对象,无非就是序列化的规则需要我们自己来写。
- 继续利用 clone() 方法,既然 clone() 方法,是我们来重写的,实际上我们可以对其内的引用类型的变量,再进行一次 clone()。
参考文章:https://segmentfault.com/a/1190000010648514