深入克隆

在继续克隆概念之前,让我们用对象创建概念刷新基础知识。 使用new运算符创建对象时,对象将在堆中获取内存分配。

堆中的对象创建

在Java中,理想情况下仅通过引用变量修改对象,即仅复制对象的内存地址,因此原始对象中的任何更改都将反映在新变量中。

Glass objGlass1 = new Glass();

Glass objGlass2 = objGlass1;

在这种情况下,在这种情况下,您对对象objGlass1所做的任何更改都会反映在对象objGlass2中 ,反之亦然。 这意味着“ objGlass1 == objGlass2 ”将返回true,这两个引用变量objGlass1objGlass2都引用同一对象。 但是,如果您打算复制对象而不是仅复制对象的引用,则需要克隆。

什么是克隆?

克隆是复制对象的过程,即通过复制自身来创建新实例。 Java中的克隆可以通过使用对象的clone()方法来完成。

克隆使用相同的类和所有字段具有相同的值来创建并返回对象的副本。

Glass objGlass1 =新的Glass();

玻璃objGlass2 =(玻璃)objGlass.clone();

克隆后,让我们看下面的分析:

  • objGlass1!= objGlass2返回TRUE,这意味着objGlass1objGlass2引用两个不同的内存位置,即两个不同的对象。
  • objGlass1.getClass()== objGlass2 .getClass()返回TRUE,这意味着克隆的对象和原始对象应该是同一类型。
  • objGlass1.equals(objGlass2)返回TRUE,这意味着克隆的对象数据应等于原始数据(但是在克隆后的任何时间都可以更改)。


浅克隆与深克隆

Java支持两种类型的克隆–浅克隆和深克隆。

如果是“ 浅”克隆,则会创建一个新对象,该对象具有原始对象中值的精确副本。 Object的clone()方法提供了浅层克隆。 在这种克隆机制中,将复制对象而不包含其包含的对象。

浅克隆仅复制对象的顶层结构,而不复制较低层。

结构形式

浅克隆结构

在上图中, OriginalObject1具有Field1和一个包含的对象,称为ReferenceObject1 。 现在,在浅克隆OriginalObject1过程中,将使用具有从Field1复制的值的Field2创建ClonedObject2 ,它仍然指向ReferenceObject1 。 这背后的原因是Field1是原始类型,因此将其值复制到Field2中 。 但是,由于ReferenceObject1是对象类型,因此ClonedObject2指向相同的ReferenceObject1

ReferenceObject1所做的任何更改都将可见ClonedObject2

浅克隆结构

如果是深度克隆 ,则复制所有字段。 在这种情况下,即使引用的对象也将与字段一起复制到克隆的对象中。

深克隆结构

如上图所示, OriginalObject1具有基本类型Field1ReferenceObject1 。 现在,当我们做OriginalObject1然后ClonedObject2字段2是具有从Field 1和ReferenceObject2含有ReferenceObject1的复制值复制的值创建沿的深克隆。

深克隆结构


浅克隆示例:

浅克隆示例

浅克隆示例

在上面的示例中,我们有一个原始对象Employee,它引用了Department类和一个字段EmployeeName 。 首先,我们假设EmployeeName =“ Chris”和DepartmentName =“ Sales”的值。 当我们通过“浅层克隆”克隆对象Employee时,将创建一个ClonedEmployee对象,该对象具有一个复制字段EmployeeName和Department的重复字段。 但是,我们需要注意的是,没有创建重复的Department对象。 克隆的Employee对象引用与所引用类Department相同的内存地址。

因此,现在当我们将EmployeeName的原始对象值更改为“ Peter”,将DepartmentName的原始对象值更改为“ Finance”时,克隆的EmployeeName字段将不会更改。 它仍然包含旧值(按照图表的上述部分)。 但是,我们必须注意,克隆的DepartmentName现在已修改为“ Finance”以反映更改。 这是因为克隆的Employee引用与原始对象相同的内存地址。 因此,对原始对象引用所做的任何更改对于引用原始对象的克隆对象也是可见的。 它不会像字段一样重复。

浅克隆的代码示例

Department.java (ReferenceObject)

public class Department {private String deptName;public Department(String str) {deptName = str;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}
}

Employee.java (主对象)

public class Employee implements Cloneable {private String employeeName;private Department dept;public String getEmployeeName() {return employeeName;}public void setEmployeeName(String employeeName) {this.employeeName = employeeName;}public Department getDept() {return dept;}public void setDept(Department dept) {this.dept = dept;}public Employee(String emp, String empDept) {employeeName = emp;dept = new Department(empDept);}public Object clone() {try {return super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

客户端程序

public static void main(String[] args) {Employee emp = new Employee('Chris', 'Sales');System.out.println('Original Object value - Employee Name:'+ emp.getEmployeeName() + ' & department name:'+ emp.getDept().getDeptName());Employee clonedEmployee = (Employee) emp.clone();System.out.println('Cloned object value - Employee Name:'+ clonedEmployee.getEmployeeName() + ' & department name:'+ clonedEmployee.getDept().getDeptName());// Now let's change values of Original Objectemp.setEmployeeName('Peter');emp.getDept().setDeptName('Finance');System.out.println('Original Object value after it is modified - Employee Name:'+ emp.getEmployeeName()+ ' & department name:'+ emp.getDept().getDeptName());System.out.println('Cloned object value after modification of original object' +' - Employee Name:'+ clonedEmployee.getEmployeeName()+ ' & department name:'+ clonedEmployee.getDept().getDeptName());}


深克隆实例

深克隆实例

与深度克隆不同,在进行深度克隆的情况下,原始对象的所有字段都将复制到克隆对象,包括原始对象引用的对象。 此过程将复制由字段指向的动态分配的内存。

在上面的示例中,即使原始对象被修改并且其值被更改,克隆对象也不会被更改,包括参考对象值,因为它没有引用相同的存储器地址。

深度克隆的代码示例:

在进行深度克隆的情况下,唯一的更改发生在clone()方法中。 与浅层克隆不同,不调用super.clone()方法,而是使用clone()方法内部的new运算符创建对象。

public Object clone() {//Deep Copy processEmployee e = new Employee(employeeName, dept.getDeptName());return e;
}

希望您喜欢这篇文章。 请随时提供您的反馈和意见。

参考:在Idiotechie博客上,我们的JCG合作伙伴 Mainak Goswami 深入探讨了克隆 。

翻译自: https://www.javacodegeeks.com/2012/11/deep-diving-into-cloning.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# 口口乱码_c# 乱码解决方法

1 设置web.configrequestEncoding"utf-8"responseEncoding"utf-8"fileEncoding"utf-8"/>如果相应使用gb2312 ,则html页面也要设置相同,解决乱码。如果为 utf-8 ,则相应的html文件的属性要转换成utf-8保存&a…

《你的灯亮着吗?》个人总结

我要如何去解决问题 搞清楚问题是什么 问题就是我们的体验和期待的所产生的差异 * 问题的本质 * 问题的定义 * 问题的产生 * 问题的表述谁需要解决问题要多维的看待问题问题来自哪里问题的解决方法在特定的层面上去解决问题问题的解决是要交给能解决问题的人--谁能解决问题别轻…

html文档的文件头的主要作用是什么,文件头

本词条缺少概述图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分。中文名文件头位 置位于文件开头任 务承担一定任务的数据类 别文…

索引和未索引执行计划的比较_详解Oracle复合索引+实例说明

复合索引复合索引顾名思义,区别于单列索引,是由两个或多个列一起构成的索引。其在B树上的数据结构是什么样?如下图,是一个包含两列的复合索引。如果你观察仔细,还会发现它的叶子节点是ASC递增排序的。现根据第一个值排…

Datables使用总结

本文共四部分:官网 | 基本使用|遇到的问题|属性表 一:官方网站:[http://www.datatables.net/] 二:基本使用:[http://www.guoxk.com/node/jquery-datatables] 1、DataTables的默认配置 $(document).ready(function() { …

python面向窗体的开发_Python高级进阶#019 pyqt5菜单menu应用,新建多窗体

知识回顾:1.掌握的是QCalendarWidget日历控件2.click点击事件(信号)触发3.掌握日期的格式化QDate本节知识视频教程以下开始文字讲解:一、案例:菜单1.新建第一个窗体2.一级菜单的配置3.二级菜单的配置4.利用菜单功能实现界面跳转,实…

用方面清理代码

在我以前的文章中,我描述了字母转换,并且提到了我们使用AspectJ解决了该任务,但是我没有提及AspectJ的工作原理以及一般性的方面。 因此,在接下来的几行中,我将解释: 什么是面向方面的编程,为什…

java前三章总结

Java前三章总结 第一章:1.Java都有什么东西? Jdk(java开发工具包)包括 Jre(Java运行环境)---------->jvm(Java虚拟机) 应用(javac) Java API和一些常用的j…

原型 - 实现自己的jQuery

每个第一次使用jq的开发者都感到惊叹,jq的$太神奇了,究竟是怎么做到的使用$控制dom 赞叹前人之余,探究其本源才是前端开发者应该做的事,社区常常说,不要重复造轮子, 可是啊,连轮子都造不出来,又怎么去了解在什么环境下用什么轮子,怎么样才可以造成更加优秀的轮子, 不同阶段对…

html 用svg缩放拉伸,html – 拉伸SVG以适应其父级的100%高度和宽度

如果您对另一种选择开放,您可以使用纯CSS创建形状.它不会像SVG那样整洁,但它会响应:* {box-sizing:border-box;}.box {margin:40px;padding:0 10px;max-width:200px;display:inline-block;vertical-align:top;border-right:2px solid green;border-left:2px solid g…

server.transfer 无法跳转页面_H5 腾讯地图无法导航

uni-app 打包H5腾讯地图无法导航前言:最近几天用uni-app开发安卓和iOS应用,打包成APP安装包后,APP内做地图导航没有问题,APP内使用的是高德地图;但是打包成为H5页面后,运行在微信内置浏览器或者运行在第三方…

打破PermGen神话

在我的最新文章中,我解释了可能导致java.lang.OutOfMemoryError:PermGen空间崩溃的原因 。 现在该讨论该问题的可能解决方案了。 或者,更确切地说,是关于互联网对可能解决方案的建议。 不幸的是,我只能说,我…

Linux获取当前年月日后缀精确到微秒,例如2017-05-06T23:57:07.713171

代码如下&#xff1a;详细见注释 #include <stdio.h> #include <string.h> #include <time.h> #include <sys/time.h>int main() {struct timeval start;struct tm *local_time NULL;static char str_time[100];char ms[16];gettimeofday( &start…

PhiloGL学习(5)——神说要有光,便有了光

前言 上一篇文章中介绍了如何创建三维对象及加载皮肤&#xff0c;本文为大家介绍如何为场景添加光源。 一、 原理分析 光在任何地方都是非常重要的&#xff0c;无论在哪里都说是要发光发热&#xff0c;光和热也是分不开的。光线分为点光源和线光源&#xff0c;所谓点光源和线光…

android 弹出弹框2秒消失_基于HTML5 Canvas 实现弹出框

前言用户鼠标移入时&#xff0c;有弹出框出现&#xff0c;这样的需求很常见。这在处理 HTML 元素实现时简单&#xff0c;但是如果是对 HTML5 Canvas 构成的图形进行处理&#xff0c;这种方法不再适用&#xff0c;因为 Canvas 使用的是另外一套机制&#xff0c;无论在 Canvas 上…

【CSS】小妙招,各种问题总结方法处理

1.实现div文字溢出自动省略号截取 overflow:hidden; /*超过部分不显示*/       text-overflow:ellipsis; /*超过部分用点点表示*/       white-space:nowrap;/*不换行*/ 2.规定行数的截取效果 text-overflow: ellipsis; /*有些示例里需要定义该属性&#xff0c…

Java2Days 2012:Java EE

Java2Days会议是东欧的主要活动&#xff0c;目的是介绍Java开发的最新趋势。 今年&#xff0c;该活动于10月25日至26日在保加利亚的索非亚举行。 我在那里&#xff0c;并有机会与一些SAP的同事一起品尝了一些最新的Java&#xff0c;云和移动内容&#xff0c;这些内容已直接发送…

html5布局总结,HTML5网页布局的总结

可以通过 和 将 html 元素组合起来。html 块元素大多数 html 元素被定义为块级元素或内联元素。编者注&#xff1a;“块级元素”译为 block level element&#xff0c;“内联元素”译为 inline element。块级元素在显示时&#xff0c;通常会以新行来开始(和结束)。例子&#x…

c++ 优先队列_C/C++数据结构:队列结构最全解析!带你零基础入门队列结构

前言上一章节针对于C语言栈结构做了解析&#xff0c;不清楚的可以回顾一下。本章节主要针对于C语言的基础数据结构队列做以解析。数据结构之队列队列是一种特殊的 线性表 &#xff0c;特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在…

bit-map再显身手:test.txt中有42亿个无符号整数, 求不存在于test.txt中的最小无符号整数。限制: 可用内存为600MB....

先看看这个题目&#xff1a;test.txt中有42亿个无符号整数&#xff0c; 求不存在于test.txt中的最小无符号整数. 限制&#xff1a; 可用内存为600MB. 又是大数据。 看到42亿&#xff0c; 有灵感没&#xff1f; 要知道&#xff0c; 2的32次方就是42亿多一点点啊。42亿个无符号…