加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java中的深克隆和浅克隆

发布时间:2020-12-14 06:40:38 所属栏目:Java 来源:网络整理
导读:为什么要克隆 首先思考一个问题,为什么需要克隆对象? 直接new一个对象不行吗? 克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的"状态"时就要靠克隆了. 当然,把对象的属性一个一个

为什么要克隆

首先思考一个问题,为什么需要克隆对象? 直接new一个对象不行吗?

克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的"状态"时就要靠克隆了.

当然,把对象的属性一个一个的赋值给新new的对象也是可以的,但是这样一来麻烦不说,二来,我们通过源码查看 Object的clone方法是一个native方法(native方法是非Java语言实现的代码,供Java程序调用,要想访问比较底层的与操作系统相关的就没办法了,只能由靠近操作系统的语言来实现),就是快啊,实在更底层实现的.

我们常见的 Object a = new Object(); Object b; b = a; 这种形式的代码复制的是引用,即对象在内存中的地址,a和b指向了同一个对象. 而通过clone方法赋值的对象跟原来的对象是同时独立存在的.

概念

浅克隆:

被克隆的对象里的所有变量值都与原来的对象相同,而所有对其他对象的引用仍然指向原来的对象. 简单说,浅克隆仅克隆当前对象,而不克隆当前对象所引用的对象.

深克隆:

被克隆的对象里的所有变量值都与原来的对象相同,那些引用其他对象的变量将指向被复制过的新对象,而不再是原来被引用的对象. 简单说,深克隆不仅克隆了当前对象,还把当前对象所引用的对象都复制了一遍.

Object中的clone

Object类中的clone()方法属于浅克隆. 它的工作原理如下: 在内存中先开辟一块和原始对象相同的空间,然后复制原始对象的内容. 对于基本数据类型,这样操作当然没问题,但对于引用类型,由于保存的仅仅是对象的引用,克隆过去的引用所指向的是同一个对象.

Java中实现浅克隆

java中实现clone要实现 Cloneable 接口,该接口十分简单,源码如下:

Java中的深克隆和浅克隆

仅仅起到一个标识的作用.

下面是一个实现浅克隆的例子:

Java中的深克隆和浅克隆

可以看到,对象确实不是原来的对象了,但是其中的引用对象却还是原来的对象.

浅克隆对于引用对象仅拷贝引用.

如果一个对象只包含原始数据或者不可变对象域(如: String),推荐使用浅克隆.

Java中实现深克隆

将类中的所有引用类型都进行clone,并重写对象clone()方法,对所有引用类型进行clone.

代码如下:

Java中的深克隆和浅克隆

将所有引用类型都进行clone,实现了深克隆.

Java序列化克隆

如果引用类型中海包括引用类型,要实现多层克隆会很麻烦,这使用可以使用序列化和反序列化的方式实现对象的深克隆.

把对象写到字节流中的过程是序列化的过程,而把对象从字节流中读出来的过程是反序列化的过程. 由于Java序列化的过程中,写在流中的是对象的一个拷贝,而原对象仍然在JVM中,所以可以利用这个原理来实现对对象的深克隆.

上面代码使用序列化实现如下:

Java中的深克隆和浅克隆

可以将序列化克隆封装为一个方法,如下所示:

Java中的深克隆和浅克隆

通过该工具类即可进行深度克隆. 要是用该方法,对象、对象的所有引用类型、引用类型中的引用类型都要实现 Serializable 接口.


当然,对象中的final对象是不能进行clone的,因为final的限制.

如果用线程安全的类实现Cloneable,要保证它的clone方法做好同步工作,默认的Object.clone方法是没有同步的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读