深入克隆

在继续克隆概念之前,让我们用对象创建概念刷新基础知识。 使用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,一经查实,立即删除!

相关文章

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

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

Datables使用总结

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

用方面清理代码

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

原型 - 实现自己的jQuery

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

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

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

打破PermGen神话

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

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

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

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

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

Java2Days 2012:Java EE

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

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

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

周期均方根和有效值的区别_黑猪肉和白猪肉有啥区别?

为啥散养黑猪肉的价格要比白猪贵很多?这其中的原因不看不知道!市面上的散养黑猪肉通常要比白猪肉贵很多,但是仍有不少人喜欢买黑猪肉回家吃,散养黑猪肉和白猪肉不仅仅是口感上有所差距,其价值差距体现在很多方面,接下来小编就和大…

测试环境搭建流程_前端构建 DevOps 搭建 DevOps 基础平台(中)

前言搭建基础平台搭建上篇的时候的时候,已经介绍过了项目流程设计、数据库搭建、jwt 登录等模块。此篇我们介绍分支管理设计及其他的基础模块。后端模块DevOps - Gitlab Api使用(已完成,点击跳转)DevOps - 搭建 DevOps 基础平台(已完成 50%)基础平台搭建…

什么是PermGen泄漏?

接下来是对Java应用程序中特定类型的内存问题的实用介绍。 即–我们将分析导致java.lang.OutOfMemoryError:PermGen空间的错误 堆栈跟踪中的症状。 首先,我们将介绍理解该主题所需的核心概念,并说明什么是对象,类,类…

rto净化效率计算公式_全面剖析 石油化工行业RTO蓄热式焚烧炉的优势要素

在我国的国民经济发展中,石油化工产业是重要的能源基础工业,但是废气的治理问题一直困扰着许多企业。直到RTO蓄热式焚烧炉的面世,为石油化工行业的废气治理带来了新希望。如今,有机废气治理工作越来越受到广泛重视,传统…

python作业:高级FTP程序

要求: 用户加密认证允许同时多用户登录每个用户有自己的家目录 ,且只能访问自己的家目录对用户进行磁盘配额,每个用户的可用空间不同允许用户在ftp server上随意切换目录允许用户查看当前目录下文件允许上传和下载文件,保证文件一…

webpack学习笔记 (一)

一、安装nodejs; 点击打开nodejs官方站点; 点击下图框住的按钮,下周nodejs安装包; 安装下载好的安装包。 安装完毕之后,在cmd中输入node -v查看是否已经安装成功 如果有版本号显示,则代表安装成功&#xf…

将涡轮增压器添加到JEE Apps

我扮演的关键角色之一是在本地社区中传播Akka。 作为讨论的一部分,人们通常会想到的问题/疑问是Akka如何针对编写良好的Java / JEE应用程序提供更好的可伸缩性和并发性。 由于底层硬件/ JVM保持不变,因此参与者模型如何比传统的JEE应用程序发挥更多的功…

MapReduce的工作原理

一、MapReduce模型框架 MapReduce是一个用于大规模数据处理的分布式计算模型,最初由Google工程师设计并实现的,Google已经将完整的MapReduce论文公开发布了。其中的定义是,MapReduce是一个编程模型,是一个用于处理和生成大规模数据…

react实现多行文本超出加省略号

http://www.css88.com/archives/5206 overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; 根据该文章方法,放在react项目中发现并不能实现,仔细观察发现原来react解析出来的css样…

qq群 html,我的群组-普通群组.html

我的群组-普通群组$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resou…