克隆、深拷贝与浅拷贝区别
1,克隆:
❀❀业务需求:保留原来的对象,但是需要一个在原来对象的信息上进行修改点信息的对象,需要使用到克隆技术-------clone();
(因为使用clone() 拷贝出来的对象,有自己的内存地址,而不是跟被拷贝对象一样指向同一个内存地址。
ps:细节:对象要使用clone()方法前,对象的类需要先实现Cloneable接口)
ps:▪clone() 跟 new 区别:new 完的对象没有原来对象的已有数据信息。
例如原来对象(学生对象:数据信息:小红、20、 100),而new 一个对象的话,这没有数据。
▪另外如果是采取直接定义引用变量stu2直接执行已经存在的学生对象stu1,两个引用指向同一个内存地址,影响是同步的,不符合咱的业务需求(原来的对象不被新产生的类所影响)。
代码:
Student stu1 = new Student(“小红”, 20, 100); Student stu2 = stu1; 此刻修改stu2,例如 stu2.setName(“小芳”); 则stu1、stu2的姓名都变成了小芳。
2,深拷贝与浅拷贝区别:
2-1:先搞懂 “引用对象”跟“对象引用”,根据语文的主干理解,“引用对象”跟“对象引用”
引用对象-------主干是对象,
对象引用-------主干是引用
“引用对象”跟“对象引用”的区别:简单理解变成变成了对象与引用的区别
例子 Class1 A = new Class1();
我们知道对象都是new 出来的,显然这里的对象(引用对象)就是 new Class1();
而引用(对象引用)就是A(因为本质讲,引用就是C语言的指针,指向的作用)。平时没考察到底层原理的,通俗理解:A就是new Class1() 起的别名。
2-2:深拷贝与浅拷贝区别:
深拷贝是针对较为复杂的object类型数据。
✿浅拷贝定义:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。
✿深拷贝定义:深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
(1)情况一:类只有基本类型的属性,没有对象引用属性。
这时候只需要clone()就可以实现克隆啦(默认情况的clone()就是浅拷贝)
(2)情况二:类除了基本类型的属性,还有对象引用属性。
实现业务采取方式一:如果只是想刚才那样,类实现Cloneable接口,然后类重写clone()方法,那么会导致两个对象的内部的对象引用属性又指向同一个内存地址。
解决1:既然内部对象引用属性出现了之前的指向同一个内存地址问题?----对于内部的对象属性的所引用的类也使用类实现接口Cloneable,重写clone()方法来解决。
解决2:利用序列化与反序列化实现(序列化就是将对象写到流中的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以
复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再反序列化从流中将其读出来,即可实现深拷贝。)这种方式才是真正意义上的的深度克隆。
2-3:深拷贝与浅拷贝区别:是否拷贝了java(引用)对象。深拷贝拷贝引用对象,而浅拷贝没有拷贝引用对象。浅拷贝只复制指向某个对象的指针,而不复制对象本身,
新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
2-4、总结:实现对象克隆有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,这种方式才是真正意义上的的深度克隆。
参考文章:https://blog.csdn.net/weixin_42857992/article/details/99338681 《序列化(Serialization)实现深拷贝》
https://blog.csdn.net/qq_35387940/article/details/107779427
《Java 对象的克隆Clone和必须了解的浅拷贝与深拷贝_默默不代表沉默-CSDN博客》
https://segmentfault.com/a/1190000018874254《浅拷贝与深拷贝的区别》
https://zhuanlan.zhihu.com/p/165203561《面试官:问点儿基础的,你能说说Java深拷贝和浅拷贝区别吗》