深入克隆

在繼續克隆概念之前,讓我們用對象創建概念刷新基礎知識。 使用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.pswp.cn/news/370803.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370803.shtml
英文地址,請注明出處:http://en.pswp.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億個無符號…