java中的三種拷貝方法

在Java編程中,理解深拷貝(Deep Copy)、淺拷貝(Shallow Copy)和引用拷貝(Reference Copy)是非常重要的。這三種拷貝方式涉及對象復制和內存管理。以下是對它們的詳細解釋:

1. 引用拷貝(Reference Copy)

引用拷貝是最簡單的一種拷貝方式。它只復制對象的引用,而不復制對象本身。換句話說,原始對象和新對象共享同一個內存地址。

Person person1 = new Person("Alice");
Person person2 = person1;  // 引用拷貝person2.setName("Bob");System.out.println(person1.getName()); // 輸出 "Bob"
System.out.println(person2.getName()); // 輸出 "Bob"

在上述代碼中,person1person2指向同一個對象,所以改變其中一個對象的屬性,另一個對象的屬性也會被改變。

2. 淺拷貝(Shallow Copy)

淺拷貝會創建一個新對象,但新對象中的成員變量(如果是對象)仍然是原對象的引用。淺拷貝僅復制對象的第一層屬性。

可以通過實現Cloneable接口并重寫clone方法來實現淺拷貝:

class Address {String city;public Address(String city) {this.city = city;}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 淺拷貝}
}public class Main {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("Alice", address);Person person2 = (Person) person1.clone();person2.name = "Bob";person2.address.city = "Los Angeles";System.out.println(person1.name); // 輸出 "Alice"System.out.println(person1.address.city); // 輸出 "Los Angeles"System.out.println(person2.name); // 輸出 "Bob"System.out.println(person2.address.city); // 輸出 "Los Angeles"}
}

在上述代碼中,person1person2擁有不同的name屬性,但是共享同一個Address對象。

3. 深拷貝(Deep Copy)

深拷貝不僅創建一個新對象,還會遞歸地復制所有成員對象。這樣,原對象和新對象完全獨立,不共享任何引用。

深拷貝可以通過手動實現clone方法來完成,或者使用序列化。

手動實現深拷貝的示例:

class Address implements Cloneable {String city;public Address(String city) {this.city = city;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {Person cloned = (Person) super.clone();cloned.address = (Address) address.clone();  // 深拷貝return cloned;}
}public class Main {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("Alice", address);Person person2 = (Person) person1.clone();person2.name = "Bob";person2.address.city = "Los Angeles";System.out.println(person1.name); // 輸出 "Alice"System.out.println(person1.address.city); // 輸出 "New York"System.out.println(person2.name); // 輸出 "Bob"System.out.println(person2.address.city); // 輸出 "Los Angeles"}
}

在上述代碼中,person1person2的所有屬性都是獨立的,修改一個對象的屬性不會影響另一個對象。
通過序列化和反序列化來實現Java的深拷貝是一種通用且方便的方法。它可以確保對象的完整復制,包括所有嵌套的成員對象。以下是具體的實現步驟:

  1. 讓類實現Serializable接口:確保需要深拷貝的類和它包含的所有成員類都實現Serializable接口。
  2. 使用序列化和反序列化進行深拷貝:將對象寫入字節流,然后從字節流中讀出對象,從而實現對象的完全復制。

下面是一個具體的例子:

示例代碼

import java.io.*;class Address implements Serializable {private static final long serialVersionUID = 1L;String city;public Address(String city) {this.city = city;}@Overridepublic String toString() {return "Address{city='" + city + "'}";}
}class Person implements Serializable {private static final long serialVersionUID = 1L;String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}@Overridepublic String toString() {return "Person{name='" + name + "', address=" + address + "}";}// 深拷貝方法public Person deepCopy() {try {// 序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);oos.flush();oos.close();// 反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (Person) ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();return null;}}
}public class Main {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("Alice", address);Person person2 = person1.deepCopy();person2.name = "Bob";person2.address.city = "Los Angeles";System.out.println("Original: " + person1);  // 原對象System.out.println("Copy: " + person2);  // 深拷貝后的對象}
}

代碼解釋

  1. 實現Serializable接口AddressPerson類都實現了Serializable接口,使它們可以被序列化。
  2. 深拷貝方法deepCopy
    • 序列化:使用ObjectOutputStream將對象寫入ByteArrayOutputStream
    • 反序列化:使用ObjectInputStreamByteArrayInputStream中讀出對象,生成一個新的對象副本。
  3. 測試深拷貝
    • 創建原始對象person1,并通過deepCopy方法生成person2
    • 修改person2的屬性,驗證原始對象person1不受影響,證明了對象的深拷貝。

這種方法的優點是實現簡單,且適用于所有需要深拷貝的情況。然而,它也有一些限制,比如性能較慢(因為涉及IO操作)和必須實現Serializable接口。

總結

  • 引用拷貝:只復制引用,原對象和新對象指向同一個對象。
  • 淺拷貝:創建新對象,但不遞歸復制成員對象,成員對象仍然是共享的引用。
  • 深拷貝:創建新對象,并遞歸復制所有成員對象,完全獨立。

這些拷貝方式在實際應用中有不同的使用場景和適用性,根據需要選擇合適的拷貝方式可以有效管理內存和對象關系。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23599.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23599.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23599.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數字IC后端物理驗證PV | TSMC 12nm Calibre Base Layer DRC案例解析

基于TSMC 12nm ARM A55 upf flow后端設計實現訓練營將于6月中旬正式開班!小班教學!目前還有3個名額,招滿為止!有需要可以私信小編 ic-backend2018報名。吾愛IC社區所有訓練營課程均為直播課! 這個課程支持升級成雙核A…

服務器禁止密碼登陸

轉載請標明出處:https://blog.csdn.net/donkor_/article/details/139444224 文章目錄 一、前言二、編輯sshd_config文件三、重啟服務四、總結 一、前言 復雜的密碼,登陸服務器的時候,也是很不方便的。并且頻繁登陸,暴露給外界&am…

事件總線vueEvent

一個組件結束后要更新另一個組件數據,但是另一個組件和這個組件沒有上下級關系 在 Vue 中,非父子組件之間進行通信通常需要使用事件總線或者其他的全局事件管理器。在你的代碼片段中,vueEvent 似乎是一個事件總線對象,通過 emit 方…

c++ 里函數選擇的優先級:普通函數、模板函數、萬能引用,編譯器選擇哪個執行呢?

看大師寫的代碼時,除了在類里定義了 copy 構造函數,移動構造函數,還定義了對形參采取萬能引用的構造函數,因此有個疑問,這時候的構造函數優先級是什么樣的呢?簡化邏輯測試一下,如下圖&#xff0…

如何實現JavaScript中的寄生組合式繼承?

在JavaScript中,寄生組合式繼承是一種繼承機制,它結合了寄生式繼承和組合繼承的特點。其核心思想是通過構造函數來繼承屬性,同時通過原型鏈來繼承方法。以下是實現寄生組合式繼承的基本步驟: 首先定義一個輔助函數 inheritProtot…

Pygame:新手指南與入門教程

在游戲開發領域,pygame 是一個廣受歡迎的 Python 庫,它提供了開發二維游戲的豐富工具和方法。這個庫讓開發者可以較少地關注底層圖形處理細節,更多地專注于游戲邏輯和玩法的實現。本文將詳細介紹 pygame,包括其安裝過程、基本概念、主要功能和一個簡單游戲的開發流程。 一…

【Vue】路由的封裝抽離

問題:所有的路由配置都在main.js中合適嗎? 目標:將路由模塊抽離出來。 好處:拆分模塊,利于維護 路徑簡寫: 腳手架環境下 指代src目錄,可以用于快速引入組件 完整代碼 router/index.js // 但…

探索貸款交易平臺的技術架構與創新應用

隨著金融科技的快速發展,貸款交易平臺作為金融行業的重要組成部分,正扮演著越來越重要的角色。本文將深入探討貸款交易平臺的技術架構和創新應用,從前端設計、后端系統、安全保障和智能化服務等方面進行全面解析,幫助讀者更好地了…

【Python報錯】已解決AttributeError: list object has no attribute ’shape‘ ( Solved )

解決Python報錯:AttributeError: ‘list’ object has no attribute ‘shape’ (Solved) 在Python中,AttributeError表明你試圖訪問的對象沒有你請求的屬性或方法。如果你遇到了AttributeError: list object has no attribute shape的錯誤,這…

為什么要用Git

1. Git是什么 1.1. 概述 Git是分布式版本控制系統,與SVN類似的集中化版本控制系統相比,集中化版本控制系統如果中央服務器宕機則會影響數據和協同開發。 Git是分布式的版本控制系統,客戶端不只是提取最新版本的快照,而且將整個…

【Java畢業設計】基于Java的特色美食推薦網站的設計與實現

文章目錄 摘 要ABSTRACT目 錄1 概述1.1 研究背景及意義1.2 國內外研究現狀1.3 擬研究內容1.4 系統開發技術1.4.1 Java編程語言1.4.2 SpringBoot框架1.4.3 MySQL數據庫1.4.4 B/S結構1.4.5 MVC模式 2 系統需求分析2.1 可行性分析2.2 任務概述2.3 功能性需求3.2.2 數據庫邏輯結構設…

全面解析如何租用免備案海外服務器

租用免備案海外服務器是許多企業和個人在全球范圍內開展業務或訪問國際互聯網資源時選擇的一種方式。這種服務具有無需經過中國互聯網備案流程的優勢,能夠快速部署并使用。下面將詳細介紹免備案海外服務器租用的相關信息,rak部落為您整理發布。 1. **國外…

外匯天眼:FSCS確認TenetConnect Services Ltd已任命管理人

2024年6月5日,Tenet Group Ltd的董事們任命了Interpath Ltd的Ed Boyle、Howard Smith和Rob Spence為聯合管理人。Ed Boyle和Rob Spence也被任命為其子公司Tenet Ltd、TenetConnect Ltd和TenetConnect Services Ltd的聯合管理人。Tenet Mortgage Services Ltd和Tenet…

【計算機視覺(8)】

基于Python的OpenCV基礎入門——圖像直方圖 直方圖圖像直方圖 圖像直方圖代碼以及實現效果 直方圖 直方圖是一種用于描述圖像亮度分布的統計工具。它將圖像的像素亮度值按照不同的亮度等級進行計數,并以直方圖的形式呈現出來。圖像直方圖可以顯示圖像中每個亮度級別…

點擊式的excel電子表格查找修改功能,比xlookup和vlookup簡單,多列關聯查詢速度更快

經過實際測試,excel的xlookup確實非常簡單,有部分功能也非常快。但是有的人不會公式,或者不喜歡用公式,或者沒有excel2021以上的版本。而且xlookup確實也有些還不是很完美的地方,比如對多列關聯查詢很慢。所以我們還是…

MVC前端怎么寫:深入解析與實戰指南

MVC前端怎么寫:深入解析與實戰指南 在Web開發領域,MVC(Model-View-Controller)是一種廣泛使用的架構模式,它將應用程序的數據、界面和控制邏輯分離,使得代碼更加清晰、易于維護。本文將詳細探討MVC前端如何…

selenium非全新的方式同時啟動多個瀏覽器又互不影響的一種實現方法,歡迎討論!

最近在做模擬瀏覽器批量定時自動點擊實現批量操作功能,主要使用selenium,但是發現selenium直接調用本地瀏覽器,啟動的是一個全新的(與手動打開的不一致),網站可以檢測到,每次都要雙重驗證(密碼登…

Windows系統中不同Java版本共存

Windows系統中不同Java版本共存的方法 在Windows系統中,有時我們需要同時運行多個Java應用,而這些應用可能依賴于不同版本的Java Development Kit (JDK) 或 Java Runtime Environment (JRE)。為了實現這種需求,我們需要在Windows中配置多個J…

我應該如何使用 Python 的 NLTK 庫進行詞頻統計?

使用Python的NLTK(Natural Language Toolkit)庫進行詞頻統計,你可以遵循以下步驟: 安裝NLTK庫: 如果你還沒有安裝NLTK,可以通過pip安裝: pip install nltk導入必要的模塊: 在Python腳…

電商APP用戶體驗提升技巧:一個實戰案例

隨著網絡和移動技術的快速發展,加上全球疫情的影響,電子商務應用程序改變了人們的購物方式,積累了大量的用戶群體。如今,一個成功的電子商務應用程序,除了網站用戶界面的美,電子商務用戶體驗的設計&#xf…