亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java中關(guān)于深拷貝的幾種方式總結(jié)

 更新時(shí)間:2022年08月18日 10:26:48   作者:凌兮~  
這篇文章主要介紹了java中關(guān)于深拷貝的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

在java里,當(dāng)我們需要拷貝一個(gè)對(duì)象時(shí),有兩種類型的拷貝:淺拷貝與深拷貝。

  • 淺拷貝只是拷貝了源對(duì)象的地址,所以源對(duì)象的值發(fā)生變化時(shí),拷貝對(duì)象的值也會(huì)發(fā)生變化。
  • 深拷貝則是拷貝了源對(duì)象的所有值,所以即使源對(duì)象的值發(fā)生變化時(shí),拷貝對(duì)象的值也不會(huì)改變。

在這里插入圖片描述

方式1:構(gòu)造函數(shù)深拷貝

我們可以調(diào)用構(gòu)造函數(shù)進(jìn)行深拷貝,形參如果是基本類型和字符串則是直接賦值,如果是對(duì)象,則是重新new一個(gè)。

測(cè)試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:28
 * 通過(guò)構(gòu)造器進(jìn)行深拷貝測(cè)試
 */
@Getter
public class UserConstruct {
    private String userName;
    private AddressConstruct address;
    public UserConstruct() {
    }
    public UserConstruct(String userName, AddressConstruct address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressConstruct address = new AddressConstruct("小區(qū)1", "小區(qū)2");
        UserConstruct user = new UserConstruct("小李", address);
        // 調(diào)用構(gòu)造函數(shù)進(jìn)行深拷貝
        UserConstruct copyUser = new UserConstruct(user.getUserName(), new AddressConstruct(address.getAddress1(), address.getAddress2()));
        // 修改源對(duì)象的值
        user.getAddress().setAddress1("小區(qū)3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1() == copyUser.getAddress().getAddress1());
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
        // true
        System.out.println(user.getAddress().getAddress2().equals(copyUser.getAddress().getAddress2()));
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:28
 */
@Getter
@Setter
public class AddressConstruct {
    private String address1;
    private String address2;
    public AddressConstruct() {
    }
    public AddressConstruct(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}

方式2:重載Clone()方法深拷貝

Object父類有個(gè)clone()的拷貝方法,不過(guò)它是protected類型的 ,我們需要重寫(xiě)它并修改為public類型,除此之外,子類還需要實(shí)現(xiàn)Cloneable接口來(lái)告訴JVM這個(gè)類上市可以拷貝的。

測(cè)試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:49
 *
 */
@Setter
@Getter
public class AddressClone implements Cloneable{
    private String address1;
    private String address2;
    public AddressClone() {
    }
    public AddressClone(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
    @Override
    protected AddressClone clone() throws CloneNotSupportedException {
        return (AddressClone) super.clone();
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:48
 * 通過(guò)實(shí)現(xiàn)Clone接口實(shí)現(xiàn)深拷貝
 */
@Setter
@Getter
public class UserClone implements Cloneable{
    private String userName;
    private AddressClone address;
    public UserClone() {
    }
    public UserClone(String userName, AddressClone address) {
        this.userName = userName;
        this.address = address;
    }
    /**
     * Object父類有個(gè)clone()的拷貝方法,不過(guò)它是protected類型的,
     * 我們需要重寫(xiě)它并修改為public類型。除此之外,
     * 子類還需要實(shí)現(xiàn)Cloneable接口來(lái)告訴JVM這個(gè)類是可以拷貝的。
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected UserClone clone() throws CloneNotSupportedException {
        // 需要注意的是,super.clone()其實(shí)是淺拷貝,
        // 所以在重寫(xiě)UserClone類的clone()方法時(shí),address對(duì)象需要調(diào)用address.clone()重新賦值
        UserClone userClone = (UserClone) super.clone();
        userClone.setAddress(this.address.clone());
        return userClone;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        AddressClone address = new AddressClone("小區(qū)1", "小區(qū)2");
        UserClone user = new UserClone("小李", address);
        UserClone copyUser = user.clone();
        user.getAddress().setAddress1("小區(qū)3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

需要注意的是,super.clone()其實(shí)是淺拷貝,所以在重寫(xiě)User類的clone()方法時(shí),address對(duì)象需要調(diào)用address.clone()重新賦值。

方式3:Apache Commons Lang序列化方式深拷貝

Java提供了序列化的能力,我們可以先將源對(duì)象進(jìn)行序列化,再反序列化生成拷貝對(duì)象。但是,使用序列化的前提是拷貝的類(包括其成員變量)需要實(shí)現(xiàn)Serializable接口。

Apache Commons Lang包對(duì)Java序列化進(jìn)行了封裝,我們可以直接使用它。

測(cè)試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
 * @author 凌兮
 * @date 2021/4/15 15:11
 */
@Getter
@Setter
public class AddressSerializable implements Serializable {
    private String address1;
    private String address2;
    public AddressSerializable() {
    }
    public AddressSerializable(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
/**
 * @author 凌兮
 * @date 2021/4/15 15:10
 * 通過(guò)Apache Commons Lang 序列化方式深拷貝
 * Java提供了序列化的能力,我們可以先將源對(duì)象進(jìn)行序列化,再反序列化生成拷貝對(duì)象。
 * 但是,使用序列化的前提是拷貝的類(包括其成員變量)需要實(shí)現(xiàn)Serializable接口。
 * Apache Commons Lang包對(duì)Java序列化進(jìn)行了封裝,我們可以直接使用它。
 */
@Getter
@Setter
public class UserSerializable implements Serializable {
    private String userName;
    private AddressSerializable address;
    public UserSerializable() {
    }
    public UserSerializable(String userName, AddressSerializable address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressSerializable address = new AddressSerializable("小區(qū)1", "小區(qū)2");
        UserSerializable user = new UserSerializable("小李", address);
        UserSerializable copyUser = SerializationUtils.clone(user);
        user.getAddress().setAddress1("小區(qū)3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

方式4:Gson序列化方式深拷貝

Gson可以將對(duì)象序列化成JSON,也可以將JSON反序列化成對(duì)象,所以我們可以用它進(jìn)行深拷貝。

測(cè)試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:31
 */
@Data
public class AddressGson {
    private String address1;
    private String address2;
    public AddressGson() {
    }
    public AddressGson(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import com.google.gson.Gson;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:30
 * 使用Gson序列化方式進(jìn)行深拷貝
 * Gson可以將對(duì)象序列化成JSON,也可以將JSON反序列化成對(duì)象,所以我們可以用它進(jìn)行深拷貝
 */
@Data
public class UserGson {
    private String userName;
    private AddressGson address;
    public UserGson() {
    }
    public UserGson(String userName, AddressGson address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressGson address = new AddressGson("小區(qū)1", "小區(qū)2");
        UserGson user = new UserGson("小李", address);
        // 使用Gson序列化進(jìn)行深拷貝
        Gson gson = new Gson();
        UserGson copyUser = gson.fromJson(gson.toJson(user), UserGson.class);
        user.getAddress().setAddress1("小區(qū)3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

方式5:Jackson序列化方式

Jackson與Gson相似,可以將對(duì)象序列化成JSON,明顯不同的地方是拷貝的類(包括其成員變量)需要有默認(rèn)的無(wú)參構(gòu)造函數(shù)。

測(cè)試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:41
 */
@Data
public class AddressJackson {
    private String address1;
    private String address2;
    public AddressJackson() {
    }
    public AddressJackson(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:40
 * 通過(guò)Jackson方式實(shí)現(xiàn)深拷貝
 * Jackson與Gson相似,可以將對(duì)象序列化成JSON,明顯不同的地方是拷貝的類(包括其成員變量)需要有默認(rèn)的無(wú)參構(gòu)造函數(shù)。
 */
@Data
public class UserJackson {
    private String userName;
    private AddressJackson address;
    public UserJackson() {
    }
    public UserJackson(String userName, AddressJackson address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) throws JsonProcessingException {
        AddressJackson address = new AddressJackson("小區(qū)1", "小區(qū)2");
        UserJackson user = new UserJackson("小李", address);
        // 使用Jackson序列化進(jìn)行深拷貝
        ObjectMapper objectMapper = new ObjectMapper();
        UserJackson copyUser = objectMapper.readValue(objectMapper.writeValueAsString(user), UserJackson.class);
        user.getAddress().setAddress1("小區(qū)3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

總結(jié)

深拷貝方法優(yōu)點(diǎn)缺點(diǎn)
構(gòu)造函數(shù)1. 底層實(shí)現(xiàn)簡(jiǎn)單 2. 不需要引入第三方包 3. 系統(tǒng)開(kāi)銷小 4. 對(duì)拷貝類沒(méi)有要求,不需要實(shí)現(xiàn)額外接口和方法1. 可用性差,每次新增成員變量都需要新增新的拷貝構(gòu)造函數(shù)
重載clone()方法1. 底層實(shí)現(xiàn)較簡(jiǎn)單 2. 不需要引入第三方包 3. 系統(tǒng)開(kāi)銷小1. 可用性較差,每次新增成員變量可能需要修改clone()方法 2. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)Cloneable接口
Apache Commons Lang序列化1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法1. 底層實(shí)現(xiàn)較復(fù)雜 2. 需要引入Apache Commons Lang第三方JAR包 3. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)Serializable接口 4. 序列化與反序列化存在一定的系統(tǒng)開(kāi)銷
Gson序列化1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法 2. 對(duì)拷貝類沒(méi)有要求,不需要實(shí)現(xiàn)額外接口和方法1. 底層實(shí)現(xiàn)復(fù)雜 2. 需要引入Gson第三方JAR包 3. 序列化與反序列化存在一定的系統(tǒng)開(kāi)銷
Jackson序列化1. 可用性強(qiáng),新增成員變量不需要修改拷貝方法1. 底層實(shí)現(xiàn)復(fù)雜 2. 需要引入Jackson第三方JAR包 3. 拷貝類(包括其成員變量)需要實(shí)現(xiàn)默認(rèn)的無(wú)參構(gòu)造函數(shù) 4. 序列化與反序列化存在一定的系統(tǒng)開(kāi)銷

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • 一文搞懂設(shè)計(jì)模式中的單例模式

    一文搞懂設(shè)計(jì)模式中的單例模式

    這篇文章主要介紹了一文搞懂設(shè)計(jì)模式中的單例模式,單例模式是最簡(jiǎn)單的設(shè)計(jì)模式之一,屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的方式,確保只有單個(gè)對(duì)象被創(chuàng)建,需要的朋友可以參考下
    2023-08-08
  • Spring MVC處理方法返回值過(guò)程解析

    Spring MVC處理方法返回值過(guò)程解析

    這篇文章主要介紹了Spring MVC處理方法返回值過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    這篇文章主要介紹了Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法,是一個(gè)非常實(shí)用的技巧,需要的朋友可以參考下
    2014-09-09
  • Maven本地存在jar包IDEA依舊爆紅的完美解決方法

    Maven本地存在jar包IDEA依舊爆紅的完美解決方法

    這篇文章主要介紹了Maven本地存在jar包IDEA依舊爆紅的完美解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • SpringBoot如何進(jìn)行業(yè)務(wù)校驗(yàn)實(shí)例詳解

    SpringBoot如何進(jìn)行業(yè)務(wù)校驗(yàn)實(shí)例詳解

    這篇文章主要給大家介紹了關(guān)于SpringBoot如何進(jìn)行業(yè)務(wù)校驗(yàn)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Spring Boot自定義配置屬性源(PropertySource)

    Spring Boot自定義配置屬性源(PropertySource)

    這篇文章主要介紹了Spring Boot自定義配置屬性源(PropertySource),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • Java使用I/O流讀取文件內(nèi)容的方法詳解

    Java使用I/O流讀取文件內(nèi)容的方法詳解

    這篇文章主要介紹了Java使用I/O流讀取文件內(nèi)容的方法,結(jié)合實(shí)例形式詳細(xì)分析了java使用I/O流讀取文件常見(jiàn)操作技巧,需要的朋友可以參考下
    2019-11-11
  • java編寫(xiě)ftp下載工具

    java編寫(xiě)ftp下載工具

    本文給大家介紹的是如何一步步實(shí)現(xiàn)使用java編寫(xiě)FTP下載工具,而且是在Linux環(huán)境下使用javac編譯的,在運(yùn)行和編譯上有些不同之處,有需要的小伙伴們參考下吧。
    2015-03-03
  • Spring Cloud Ribbon實(shí)現(xiàn)客戶端負(fù)載均衡的方法

    Spring Cloud Ribbon實(shí)現(xiàn)客戶端負(fù)載均衡的方法

    本篇文章主要介紹了Spring Cloud Ribbon實(shí)現(xiàn)客戶端負(fù)載均衡的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • java 中break如何跳出外部循環(huán)

    java 中break如何跳出外部循環(huán)

    這篇文章主要介紹了java 中break如何跳出外部循環(huán),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07

最新評(píng)論