Java對象拷貝實現方式

在Java開發過程中,經常需要針對對象進行拷貝操作。這是因為,在某些場景下,我們需要創建新的對象,但是這些新的對象需要與已有的對象具有相同的屬性值。

本文將介紹多種Java對象拷貝的實現方式,包括深拷貝、淺拷貝、序列化、BeanUtils、Cloneable等方式,並對每種方式的優缺點進行比較和討論。

一、深拷貝

深拷貝是指拷貝對象的所有屬性,包括對象中的引用類型屬性。當對象中存在引用類型的屬性時,深拷貝將會遞歸地拷貝該引用類型的對象。

1. 方式一:手動拷貝

手動拷貝方式是最原始的實現方式,通過遍歷對象中的每一個屬性,遞歸拷貝對象中的引用類型屬性。下面是一個示例:

public class Person {
    private String name;
    private Address address;

    // 省略 getter 和 setter 方法

    public Person deepClone() {
        Person newPerson = new Person();
        newPerson.setName(this.getName());

        Address newAddress = new Address();
        newAddress.setCity(this.getAddress().getCity());
        newAddress.setStreet(this.getAddress().getStreet());
        newPerson.setAddress(newAddress);

        return newPerson;
    }
}

public class Address {
    private String city;
    private String street;

    // 省略 getter 和 setter 方法

}

public class Demo {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("張三");

        Address address = new Address();
        address.setCity("杭州");
        address.setStreet("西湖區");

        person.setAddress(address);

        Person newPerson = person.deepClone();
    }
}

2. 方式二:序列化

使用序列化方式也可以實現對象的深拷貝,不需要手動遞歸拷貝對象中的引用類型屬性。但是,被拷貝的對象以及對象中的所有引用類型屬性都需要實現序列化介面。下面是一個示例:

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Address address;

    // 省略 getter 和 setter 方法

    public Person deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (Person) ois.readObject();
    }
}

public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    private String city;
    private String street;

    // 省略 getter 和 setter 方法

}

public class Demo {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("張三");

        Address address = new Address();
        address.setCity("杭州");
        address.setStreet("西湖區");

        person.setAddress(address);

        Person newPerson = person.deepClone();
    }
}

二、淺拷貝

淺拷貝是指只拷貝對象的基本類型屬性,不拷貝對象中的引用類型屬性。拷貝之後的對象與原對象共享引用類型屬性的內存地址。

1. Cloneable介面實現

Cloneable介面是一個標記介面,實現該介面的對象可以被克隆。但是,需要注意的是,Cloneable介面並沒有定義任何方法。如果要實現Cloneable介面,需要重寫Object類中的clone()方法,並且為該方法添加public修飾符。

public class Address {
    private String city;
    private String street;

    // 省略 getter 和 setter 方法

}

public class Person implements Cloneable {
    private String name;
    private Address address;

    // 省略 getter 和 setter 方法

    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
}

public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        person.setName("張三");

        Address address = new Address();
        address.setCity("杭州");
        address.setStreet("西湖區");

        person.setAddress(address);

        Person newPerson = person.clone();
    }
}

2. BeanUtils.copyProperties()

BeanUtils.copyProperties()是一個高效便捷的對象屬性拷貝工具,可以將源對象的屬性值拷貝到目標對象中。但是,BeanUtils.copyProperties()只能實現淺拷貝,無法拷貝引用類型屬性。

public class Address {
    private String city;
    private String street;

    // 省略 getter 和 setter 方法

}

public class Person {
    private String name;
    private Address address;

    // 省略 getter 和 setter 方法

}

public class Demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Person person = new Person();
        person.setName("張三");

        Address address = new Address();
        address.setCity("杭州");
        address.setStreet("西湖區");

        person.setAddress(address);

        Person newPerson = new Person();

        BeanUtils.copyProperties(newPerson, person);

    }
}

三、總結

本文介紹了Java中多種對象拷貝的實現方式,以及每種方式的優缺點和適用場景。在選擇對象拷貝方式時,需要根據拷貝的深度、效率和對原對象屬性的影響等方面進行綜合考慮,以選取最合適的方式。

原創文章,作者:VCWL,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/148847.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
VCWL的頭像VCWL
上一篇 2024-11-04 17:48
下一篇 2024-11-04 17:49

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論