Java中的深克隆和浅克隆
为什么要克隆
首先思考一个问题, 为什么需要克隆对象? 直接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 接口, 该接口十分简单, 源码如下:
仅仅起到一个标识的作用.
下面是一个实现浅克隆的例子:
可以看到, 对象确实不是原来的对象了, 但是其中的引用对象却还是原来的对象.
浅克隆对于引用对象仅拷贝引用.
如果一个对象只包含原始数据或者不可变对象域(如: String), 推荐使用浅克隆.
Java中实现深克隆
将类中的所有引用类型都进行clone, 并重写对象clone()方法, 对所有引用类型进行clone.
代码如下:
将所有引用类型都进行clone, 实现了深克隆.
Java序列化克隆
如果引用类型中海包括引用类型, 要实现多层克隆会很麻烦, 这使用可以使用序列化和反序列化的方式实现对象的深克隆.
把对象写到字节流中的过程是序列化的过程, 而把对象从字节流中读出来的过程是反序列化的过程. 由于Java序列化的过程中, 写在流中的是对象的一个拷贝, 而原对象仍然在JVM中, 所以可以利用这个原理来实现对对象的深克隆.
上面代码使用序列化实现如下:
可以将序列化克隆封装为一个方法, 如下所示:
通过该工具类即可进行深度克隆. 要是用该方法, 对象、对象的所有引用类型、引用类型中的引用类型都要实现 Serializable 接口.
当然, 对象中的final对象是不能进行clone的, 因为final的限制.
如果用线程安全的类实现Cloneable, 要保证它的clone方法做好同步工作, 默认的Object.clone方法是没有同步的.
Java中的深克隆和浅克隆的更多相关文章
- 浅谈Java中的深克隆和浅克隆(阿里面试)
在最近的秋招中,阿里和多益网络都问到了这个问题,虽然很简单,但是我还是想总结一下,感兴趣的可以看一下我的个人博客网站(Spring+MyBatis+redis+nginx+mysql)(适合菜鸟),最 ...
- Java克隆--深克隆与浅克隆的区别
克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...
- JAVA深复制(深克隆)与浅复制(浅克隆)
1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. 1. ...
- JAVA深克隆与浅克隆1
复制就是得到一个副本 克隆就是复制一个对象的复本.但一个对象中可能有基本数据类型,如:int,long,float 等,也同时含有非基本数据类型如(数组,集合等)被克隆得到的对象基本类型的值修改 ...
- Java中如何克隆集合——ArrayList和HashSet深拷贝
编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...
- Java中的深拷贝和浅拷贝
1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...
- Java中对象的深复制和浅复制详解
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- Java中的深复制与浅复制
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...
- 分析java中clone()方法 (转载+修改)
Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...
随机推荐
- 全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等
1.引言 对于互联网,域名是访问的第一跳,而这一跳很多时候会“失足”(尤其是移动端网络),导致访问错误内容.失败连接等,让用户在互联网上畅游的爽快瞬间消失. 而对于这关键的第一跳,包括鹅厂在内的国 ...
- PHP实现大文件下载
实现大文件下载的关键在于循环读取字节流 function downloadFile($filename) { //获取文件的扩展名 $allowDownExt = array ( 'rar', 'zi ...
- Java之JDK7的新语法探索
Java之JDK7的新语法探索 前言 感谢! 承蒙关照~ 字面量: 各种精致的表达方式: 八进制以0开头,十六进制0X开头,二进制以0B开头. 二进制运算时,应该写成这样才直观: &15 -& ...
- [Postman]代理(16)
代理服务器充当内部网络和Internet之间的安全屏障,使Internet上的其他人无法访问内部网络上的信息. 什么是代理? 在基本网络中,客户端向服务器发出请求,服务器发回响应. 代理服务器是充当计 ...
- Java-redis-雪崩优化
缓存失效的时候如下图: 解决办法"使用互斥锁(mutex key):下面是核心伪代码 v = memcache.get(key); if (v == null) { if (memcache ...
- Python - 使用Setuptools进行程序打包
1- Setuptools简介 通过Setuptools可以更方便的创建和发布Python包,特别是那些对其它包具有依赖性的状况: Python打包用户指南(Python Packaging User ...
- HBase数据持久化之HRegion.flushcache即CF持久化
我们从HRegion.flushcache开始分析.由于这个过程还是比较复杂的,因此,在这一节,我们不会分析的太过详细,只是单单的介绍一下其大体流程,待大家有了整体的把握之后,我们将在下一节详细介绍其 ...
- mongoose的基本操作方法
mongoose 1. const mongoose = require("mongoose");导入mongoose模块 2. //注意url地址最后面的地址是数据库的名称 ...
- Linux编程 19 编辑器(vim 用法)
一.概述 在开启shell脚本编程之前,必须要知道一款文本编辑器的用法,如文本编辑的查找,剪切,粘贴,定位等, 本篇只讲vim编辑器.vim编辑器全名叫vi improved,是经过对Unix系统vi ...
- 五款实用免费的Python机器学习集成开发环境(5 free Python IDE for Machine Learning)(图文详解)
前言 集成开发环境(IDE)是提供给程序员和开发者的一种基本应用,用来编写和测试软件.一般而言,IDE 由一个编辑器,一个编译器(或称之为解释器),和一个调试器组成,通常能够通过 GUI(图形界面)来 ...