链接克隆 完整克隆_深入克隆

链接克隆 完整克隆

在继续克隆概念之前,让我们用对象创建概念刷新基础知识。 使用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/351349.shtml

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

相关文章

linux系统调用和库函数调用的区别

Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。可以参考《Linux程序设计》(英文原版为《Beginning Linux Programming》,作者是Neil Matthew和Richard S…

如果您在2016年编写过Java代码-这是您不容错过的趋势

2016年最有趣的Java相关主题 关于代码,有很多热门话题,而要跟上所有事情,这是一项全职的工作。 如果您想知道如何从谷壳中分离出小麦,我们已经为您完成了工作。 在下面的文章中,我们将介绍2016年最热门的内容&#x…

第三届蓝桥杯省赛---第39级台阶

第39级台阶 小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级! 站在台阶前,他突然又想着一个问题: 如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替&#xf…

android 视图覆盖,如何在Android中添加覆盖视图超过其他视图?

设为背景!只是开玩笑…你需要的是把你的意见放在一个RelativeLayout里.会有什么工作:xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"fill_parent"android:layout_height"fill_parent"&…

Linux内核源码分析方法

一、内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次。如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径。我们都知道,想成为优秀的程序…

深度学习框架Keras介绍及实战

Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行。Keras 的开发重点是支持快速的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。 本文以Kaggle上的项目:IMDB影评情感分析为例,…

操作系统--处理机调度

4 处理机调度 4.1 调度类型 操作系统必须为多个进程的竞争请求分配计算机资源。处理机调度的任务就是选出待分派的作业或进程,为之分配处理机。 为了便于处理机调度管理,通常在处理机调度中采用分级调度方式,其中包括以下3级调度:…

permgen_什么是PermGen泄漏?

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

TP、PHP同域不同子级域名共享Session、单点登录

TP、PHP同域不同子级域名共享Session、单点登录 目的: 为了部署同个域名下不同子级域名共享会话,从而实现单点登录的问题,一处登录,同域处处子系统即可以实现自动登录。 PHP支持通过设置cookie使得同域不同子域共享SESSION 1. 通…

html语言书写注意事项,HTML注意事项(学习笔记)

1、在所有浏览器中都是有效的,但使用 其实是更长远的保障。类似的标签也一样2、标签最好用小写,未来的版本中可能强制用小写3、标签属性始终为属性值加引号属性值应该始终被包括在引号内。双引号是最常用的,不过使用单引号也没有问题。在某些…

UTF-8、GB2312、GB18030、GBK和BIG5等字符集编码范围的具体说明

一预备知识 1,字符:字符是抽象的最小文本单位。 它没有固定的形状(可能是一个字形),而且没有值。 “A”是一个字符,“”(德国、法国和许多其他欧洲国家通用货币的标志)也是一个字…

使用Forge,WildFly Swarm和Arquillian开发微服务

在本文中,我们将看到如何使用WildFly Swarm和Forge开发微服务,以及如何使用Arquillian和Rest Assured对其进行测试。 WildFly Swarm提供了一种创新的方法来打包和运行Java EE应用程序,方法是将它们与足够的服务器运行时一起打包以“ java -j…

html页面加载时触发的方法,在页面加载时触发onchange html事件

好的,我在select字段上有一个onchange事件。它现在很棒。当下拉“网络”更改时,它会刷新第二个下拉列表。我还希望顶部的ajax代码在页面加载和onchange上触发,以便填充第二个列表。这是因为它在编辑页面上。这是使用第一个的ajax调用function…

PYTHON-进阶-编码处理小结

开始 用python处理中文时,读取文件或消息,http参数等等 一运行,发现乱码(字符串处理,读写文件,print) 然后,大多数人的做法是,调用encode/decode进行调试,并没有明确思考为何出现乱码…

华为鸿蒙话题作文800字,关于鸿蒙OS 华为最高层发布最新通知:统一口径-华为,智能手机,鸿蒙...

6月2日晚,华为正式推出了HarmonyOS(鸿蒙操作系统),引发了国内外空前关注。OS操作系统是中国手机甚至整个科技行业的弱点,因此鸿蒙OS带来的震撼及争议都很多,甚至华为内部员工对它的认知也不相同。为此华为总裁办昨天发布了题为《关…

8-4 Fabled Rooks uva11134

题意:你的任务是在n*n的棋盘上放 n 小于5000 个车 使得任意两个车不互相攻击 且第i个车在一个给定的矩形ri之内 给出该矩形左上角坐标和右下角坐标四个点 必须满足放车的位置在矩形内 边上也行 如果无解输出IMPSSIBLE 行与列是独立的 所以可以分割成两个一模一…

谷歌guava_Google Guava MultiMaps

谷歌guava番石榴 这是我尝试解释和探索Google很棒的Guava java库的系列文章中的第一篇。 我在搜索Apache Commons Collections的通用版本时遇到了番石榴(Guava)–我需要一个Bimap并且厌倦了必须使用强制类型转换来填充我的代码–但是我发现要好得多。 …

python 获取系统相关编码的函数

怎么避免UnicodeEncodeError: ‘ascii’ codec can’t…类似的错误? 1、首先在py文件头部指定文件内容编码,例如:# coding: utf8 2、文件保存的时候要和py文件头部编码一致 3、在用decode和encode的时候,一定要确认要转换的字符原…

百度的html代码是什么,百度网页源代码是什么?

2017-07-28Java抓取网页的内容代码是什么public static String getHtmlReadLine(String httpurl){String CurrentLine”";String TotalString”";InputStream urlStream;String content”";try {URL url new URL(httpurl);// URL url new URL(“http://www。 …

html中高与行高的区别,深入了解css的行高Line Height属性

什么是行间距?古时候我们是用印刷机来处理文字,印出来的每个字都位于独立的一个块里。行间距,即传说中控制两行文字之间垂直距离的东东。在CSS,line-height被用来控制行与行之间的垂直距离。不过行间距与半行间距还是取决于CSS中的…