Java 深度復制對象:從基礎到實戰

目錄

    • 一、深度復制的概念
    • 二、實現深度復制的方法
      • 1. 使用序列化
      • 2. 手動實現深度復制
    • 三、總結

在 Java 編程中,對象的復制是一個常見的需求。然而,簡單的復制操作(如直接賦值)只會復制對象的引用,而不是創建一個新的對象。這意味著兩個引用會指向同一個內存地址,修改其中一個對象會影響另一個對象。為了解決這個問題,我們需要實現對象的深度復制。本文將詳細介紹如何在 Java 中實現對象的深度復制,并通過具體代碼示例幫助你更好地理解和應用這一技術。

一、深度復制的概念

深度復制是指創建一個新對象,并將原對象的所有字段值復制到新對象中。如果字段是基本數據類型,則直接復制其值;如果字段是引用類型,則需要遞歸地創建該引用對象的深度副本。這樣可以確保新對象與原對象在內存中完全獨立,修改其中一個不會影響另一個。

二、實現深度復制的方法

1. 使用序列化

Java 的序列化機制可以將對象轉換為字節流,然后再將字節流還原為對象。這一過程實際上創建了一個對象的深度副本。

import java.io.*;public class DeepCloneExample implements Serializable {private String name;private TransientData transientData;public DeepCloneExample(String name, TransientData transientData) {this.name = name;this.transientData = transientData;}public String getName() {return name;}public TransientData getTransientData() {return transientData;}@Overridepublic String toString() {return "DeepCloneExample{" +"name='" + name + '\'' +", transientData=" + transientData +'}';}public static DeepCloneExample deepClone(DeepCloneExample obj) throws IOException, ClassNotFoundException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(obj);objectOutputStream.close();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);DeepCloneExample clonedObj = (DeepCloneExample) objectInputStream.readObject();objectInputStream.close();return clonedObj;}
}class TransientData implements Serializable {private int value;public TransientData(int value) {this.value = value;}@Overridepublic String toString() {return "TransientData{" +"value=" + value +'}';}
}

2. 手動實現深度復制

對于某些復雜對象,手動實現深度復制可能更高效。這需要為每個需要復制的對象編寫自定義的 clone 方法。

public class DeepCopyExample {private int id;private String name;private Address address;public DeepCopyExample(int id, String name, Address address) {this.id = id;this.name = name;this.address = address;}public DeepCopyExample deepCopy() {Address copiedAddress = new Address(this.address.getStreet(), this.address.getCity());return new DeepCopyExample(this.id, this.name, copiedAddress);}@Overridepublic String toString() {return "DeepCopyExample{" +"id=" + id +", name='" + name + '\'' +", address=" + address +'}';}public static void main(String[] args) {Address originalAddress = new Address("123 Main St", "Anytown");DeepCopyExample original = new DeepCopyExample(1, "Example", originalAddress);DeepCopyExample copy = original.deepCopy();System.out.println("Original: " + original);System.out.println("Copy: " + copy);original.getAddress().setCity("New City");System.out.println("After changing original's address city:");System.out.println("Original: " + original);System.out.println("Copy: " + copy);}
}class Address {private String street;private String city;public Address(String street, String city) {this.street = street;this.city = city;}public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}@Overridepublic String toString() {return "Address{" +"street='" + street + '\'' +", city='" + city + '\'' +'}';}
}

三、總結

深度復制是 Java 編程中一個重要的概念,它可以確保對象的獨立性,避免意外的修改。通過本文的介紹,我們學習了兩種實現深度復制的方法:使用序列化和手動實現。每種方法都有其適用場景和優缺點。在實際開發中,選擇合適的方法來實現對象的深度復制,可以提高代碼的健壯性和可維護性。

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

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

相關文章

C++ Primer 交換操作

歡迎閱讀我的 【CPrimer】專欄 專欄簡介:本專欄主要面向C初學者,解釋C的一些基本概念和基礎語言特性,涉及C標準庫的用法,面向對象特性,泛型特性高級用法。通過使用標準庫中定義的抽象設施,使你更加適應高級…

FFmpeg-chapter7和chapter8-使用 FFmpeg 解碼視頻(原理篇和實站篇)

解碼流程如下圖 流程:首先,通過 avcodec_alloc_context3(nullptr) 分配一個 AVCodecContext 結構體,然后使用 avcodec_parameters_to_context 將參數復制到上下文中,接著通過 avcodec_find_decoder 查找指定的解碼器,并…

2025 docker安裝TiDB數據庫

1.確保安裝了docker和docker-compose sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod x /usr/local/bin/docker-compose2.編寫 Docker Compose 文…

定制化開發的WooCommerce獨立站商城更安全

定制化開發的WooCommerce獨立站商城在安全性、交易風險控制以及整體用戶體驗方面有顯著優勢。以下是定制化開發在這些方面的具體表現: 1. 安全性更高 定制化開發允許開發者從底層架構開始設計和優化,確保網站的安全性。以下是具體表現: (1…

CSS【實戰】模擬 html 的 title 屬性(鼠標懸浮顯示提示文字)

效果 原理 提示內容的定位&#xff1a;子絕父相鼠標懸浮前&#xff0c;提示內容visibility: hidden;通過 :hover 觸發鼠標懸浮樣式&#xff0c;提示內容變為 visibility: visible; 代碼 <!DOCTYPE html> <html lang"en"><head><meta charset&qu…

K8s控制器Deployment詳解

回顧 ReplicaSet 控制器,該控制器是用來維護集群中運行的 Pod 數量的&#xff0c;但是往往在實際操作的時候&#xff0c;我們反而不會去直接使用 RS&#xff0c;而是會使用更上層的控制器&#xff0c;比如說 Deployment。 Deployment 一個非常重要的功能就是實現了 Pod 的滾動…

【MYSQL數據庫異常處理】執行SQL語句報超時異常

MYSQL執行SQL語句異常&#xff1a;The last packet successfully received from the server was 100,107 milliseconds ago. The last packet sent successfully to the server was 100,101 milliseconds ago. 這個錯誤表明 MySQL 服務器與 JDBC 連接之間的通信超時了。通常由…

HJ C++11 Day2

Initializer Lists 對于一個類P class P{P(int a, int b){cout << "P(int, int), a" << a << ", b " << b << endl;}P(initializer_list<int> initlist){cout << "P(initializer_list<int>), val…

樹莓派5首次開機保姆級教程(無顯示器通過VNC連接樹莓派桌面)

第一次開機詳細步驟 步驟一&#xff1a;樹莓派系統燒錄1 搜索打開燒錄軟件“Raspberry Pi Imager”2 選擇合適的設備、系統、SD卡3 燒錄配置選項 步驟二&#xff1a;SSH遠程樹莓派1 樹莓派插電2 網絡連接&#xff08;有線或無線&#xff09;3 確定樹莓派IP地址 步驟三&#xff…

裝飾器模式--RequestWrapper、請求流request無法被重復讀取

目錄 前言一、場景二、原因分析三、解決四、更多 前言 曾經遇見這么一段代碼&#xff0c;能看出來是把request又重新包裝了一下&#xff0c;核心信息都不會改變 后面了解到這叫 裝飾器模式&#xff08;Decorator Pattern&#xff09; &#xff1a;也稱為包裝模式(Wrapper Pat…

大語言模型進化論:從達爾文到AI的啟示與展望

文章大綱 引言大語言模型中的“進化論”思想體現遺傳變異過度繁殖和生存斗爭大模型“過度繁殖”與“生存競爭”機制解析**一、過度繁殖:技術迭代的指數級爆發****二、生存競爭:計算資源的達爾文戰場****三、生存競爭勝出關鍵要素****四、行業競爭格局演化趨勢**核心結論自然選…

監聽 RabbitMQ 延時交換機的消息數、OpenFeign 路徑參數傳入斜杠無法正確轉義

背景 【MQ】一套為海量消息和高并發熱點消息&#xff0c;提供高可用精準延時服務的解決方案 我現在有一個需求&#xff0c;就是監聽 RabbitMQ 一個延時交換機的消息數&#xff0c;而 RabbitTemplate 是不存在對應的方法來獲取的。 而我們在 RabbitMQ 的控制臺卻可以發現延時交…

分布式網絡

分布式網絡&#xff08;Distributed Network&#xff09;指的是一種計算機網絡架構&#xff0c;其中計算資源&#xff08;計算、存儲、數據處理等&#xff09;分布在多個物理或邏輯上的節點上&#xff0c;而不是集中在單一的服務器或數據中心中。這種架構的主要目標是提高系統的…

【Elasticsearch】Elasticsearch 中使用 HDFS 存儲快照

在 Elasticsearch 中使用 HDFS 存儲快照的步驟如下&#xff1a; 1.安裝 HDFS 插件 要使用 HDFS 存儲 Elasticsearch 的索引快照&#xff0c;需要在 Elasticsearch 集群的所有節點上安裝 HDFS 插件。 ? 在線安裝&#xff1a;適用于網絡環境良好的場景&#xff0c;執行以下命…

淺談 DeepSeek 對 DBA 的影響

引言&#xff1a; 在人工智能技術飛速發展的背景下&#xff0c;DeepSeek 作為一款基于混合專家模型&#xff08;MoE&#xff09;和強化學習技術的大語言模型&#xff0c;正在重塑傳統數據庫管理&#xff08;DBA&#xff09;的工作模式。通過結合其強大的自然語言處理能力、推理…

STM32F4 UDP組播通信:填一填ST官方HAL庫的坑

先說寫作本文的原因&#xff0c;由于開項目開發中需要用到UDP組播接收的功能&#xff0c;但是ST官方沒有提供合適的參考&#xff0c;使用STM32CubeMX生成的代碼也是不能直接使用的&#xff0c;而我在網上找了一大圈&#xff0c;也沒有一個能夠直接解決的方案&#xff0c;deepse…

leetcode日記(85)驗證二叉搜索樹

不難&#xff0c;有兩種解法&#xff08;看答案才想到中序遍歷&#xff09;。 我用的是普通遞歸&#xff0c;和上一題差不多&#xff0c;規定min和max&#xff0c;每次遍歷縮小范圍: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNod…

如何在rust中解析 windows 的 lnk文件(快捷方式)

一、從標題二開始看&#x1f601; 這些天在使用rust寫一個pc端應用程序&#xff0c;需要解析lnk文件獲取lnk的圖標以及原程序地址&#xff0c;之前并沒有過pc端應用程序開發的經驗&#xff0c; 所以在廣大的互聯網上游蕩了兩天。額&#x1f97a; 今天找到了這個庫 lnk_parse很…

啟動wsl里的Ubuntu24報錯:當前計算機配置不支持 WSL2,HCS_E_HYPERV_NOT_INSTALLED

問題&#xff1a;啟動wsl里的Ubuntu24報錯 報錯信息&#xff1a; 當前計算機配置不支持 WSL2。 請啟用“虛擬機平臺”可選組件&#xff0c;并確保在 BIOS 中啟用虛擬化。 通過運行以下命令啟用“虛擬機平臺”: wsl.exe --install --no-distribution 有關信息&#xff0c;請訪…

Python使用FastAPI結合Word2vec來向量化200維的語言向量數值

準備 pip install fastapi>0.68.0 pip install uvicorn[standard]>0.15.0 pip install gensim>4.0.0 pip install jieba>0.42.1 pip install numpy>1.21.0 pip install scikit-learn>1.0.0少了的就直接補充就好 代碼 from fastapi import FastAPI, HTTPExc…