最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java拷貝之淺拷貝與深拷貝詳解

 更新時(shí)間:2026年02月25日 15:18:48   作者:柒.梧.  
本文主要介紹了Java中的淺拷貝和深拷貝,文章總結(jié)了淺拷貝和深拷貝的核心區(qū)別,以及在實(shí)際開(kāi)發(fā)中如何選擇合適的方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

在Java開(kāi)發(fā)中,對(duì)象拷貝是高頻場(chǎng)景——無(wú)論是業(yè)務(wù)數(shù)據(jù)復(fù)用、集合操作,還是多線程環(huán)境下的資源隔離,都離不開(kāi)拷貝操作。但很多開(kāi)發(fā)者容易混淆淺拷貝深拷貝,導(dǎo)致出現(xiàn)“修改拷貝對(duì)象,原對(duì)象莫名變化”的bug,甚至引發(fā)線上故障。

今天這篇博客,將從“概念本質(zhì)→可視化示意圖→完整代碼實(shí)例→誤區(qū)拆解”四個(gè)層面,徹底講透Java的淺拷貝與深拷貝,結(jié)合實(shí)戰(zhàn)案例演示每種拷貝方式的用法、優(yōu)缺點(diǎn),以及最容易踩的坑(比如clone方法的“偽深拷貝”),新手能快速入門,老手能查漏補(bǔ)缺,干貨無(wú)冗余。

先拋出核心結(jié)論(必記): - 淺拷貝:拷貝的是原對(duì)象的地址引用,原對(duì)象與拷貝對(duì)象共享底層數(shù)據(jù),一方修改,另一方隨之變化; - 深拷貝:拷貝的是原對(duì)象的所有數(shù)據(jù)(值拷貝),原對(duì)象與拷貝對(duì)象完全獨(dú)立,一方修改,另一方不受任何影響。

一、淺拷貝:“共享底層,牽一發(fā)而動(dòng)全身”

淺拷貝的核心邏輯的是“拷貝引用,不拷貝數(shù)據(jù)本身”。就像兩個(gè)人共用一把鑰匙,無(wú)論誰(shuí)打開(kāi)房門、修改房間里的東西,另一個(gè)人看到的都是修改后的結(jié)果——原對(duì)象和拷貝對(duì)象指向的是同一塊內(nèi)存地址,本質(zhì)上還是同一個(gè)對(duì)象的“別名”。

淺拷貝示意圖(通俗理解)

「原對(duì)象」→ 內(nèi)存地址A(存儲(chǔ)數(shù)據(jù):username=張三,password=123456) 「拷貝對(duì)象」→ 直接指向內(nèi)存地址A(未創(chuàng)建新內(nèi)存,僅拷貝原對(duì)象的地址引用) 當(dāng)拷貝對(duì)象修改username為“李四”,本質(zhì)是修改內(nèi)存地址A中的數(shù)據(jù),原對(duì)象讀取的也是地址A的數(shù)據(jù),因此會(huì)同步變化。

實(shí)戰(zhàn)演示:淺拷貝的基本用法與現(xiàn)象

我們通過(guò)簡(jiǎn)單的Java代碼,直觀感受淺拷貝的特性——定義User類,通過(guò)“直接賦值”的方式實(shí)現(xiàn)淺拷貝(Java中直接賦值就是最基礎(chǔ)的淺拷貝)。

步驟1:定義User實(shí)體類

/**
 * 實(shí)體類:用于演示拷貝操作
 * 包含用戶名、密碼兩個(gè)基本類型屬性
 */
public class User {
    // 基本類型屬性(默認(rèn)值初始化)
    private String username = "張三";
    private String password = "123456";
    // getter/setter方法(用于讀取和修改屬性值)
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

步驟2:編寫測(cè)試類,實(shí)現(xiàn)淺拷貝并驗(yàn)證

/**
 * 拷貝測(cè)試類
 * 演示淺拷貝的特性:原對(duì)象與拷貝對(duì)象相互影響
 */
public class CopyTest {
    public static void main(String[] args) {
        // 1. 創(chuàng)建原對(duì)象user01
        User user01 = new User();
        // 2. 淺拷貝:直接賦值(拷貝地址引用)
        User user02 = user01;
        // 3. 修改拷貝對(duì)象user02的username
        user02.setUsername("李四");
        // 打印原對(duì)象和拷貝對(duì)象的username
        System.out.println("修改user02的username后:");
        System.out.println("user01的username:" + user01.getUsername());
        System.out.println("user02的username:" + user02.getUsername());
        System.out.println("-----------------------------------");
        // 4. 修改原對(duì)象user01的password
        user01.setPassword("654321");
        // 打印原對(duì)象和拷貝對(duì)象的password
        System.out.println("修改user01的password后:");
        System.out.println("user01的password:" + user01.getPassword());
        System.out.println("user02的password:" + user02.getPassword());
    }
}

運(yùn)行結(jié)果與分析

修改user02的username后:
user01的username:李四
user02的username:李四
-----------------------------------
修改user01的password后:
user01的password:654321
user02的password:654321

結(jié)果很明顯: 1. 修改拷貝對(duì)象user02的username,原對(duì)象user01的username同步變成“李四”; 2. 修改原對(duì)象user01的password,拷貝對(duì)象user02的password同步變成“654321”。

核心原因:user01和user02指向同一塊內(nèi)存地址,兩者是“綁定關(guān)系”,無(wú)論修改哪一個(gè),本質(zhì)都是修改同一塊內(nèi)存中的數(shù)據(jù),自然會(huì)相互影響。

注意:淺拷貝并非毫無(wú)用處,當(dāng)我們僅需要“復(fù)用對(duì)象引用”,不需要修改數(shù)據(jù)時(shí),淺拷貝是高效的(無(wú)需創(chuàng)建新內(nèi)存,開(kāi)銷極小);但如果需要“數(shù)據(jù)隔離”,淺拷貝就會(huì)引發(fā)bug。

二、深拷貝:“完全獨(dú)立,各自安好”

深拷貝的核心邏輯是“拷貝數(shù)據(jù)本身,不拷貝地址引用”。就像兩個(gè)人各自擁有一把獨(dú)立的鑰匙,各自的房間完全獨(dú)立,無(wú)論誰(shuí)修改自己房間里的東西,都不會(huì)影響到另一方——原對(duì)象和拷貝對(duì)象指向的是不同的內(nèi)存地址,是兩個(gè)完全獨(dú)立的對(duì)象,只是初始數(shù)據(jù)相同。

深拷貝示意圖(通俗理解)

「原對(duì)象」→ 內(nèi)存地址A(存儲(chǔ)數(shù)據(jù):username=張三,password=123456) 「拷貝對(duì)象」→ 新建內(nèi)存地址B(復(fù)制地址A中的所有數(shù)據(jù),初始值與原對(duì)象一致) 當(dāng)拷貝對(duì)象修改username為“李四”,僅修改內(nèi)存地址B中的數(shù)據(jù),原對(duì)象讀取的還是地址A的數(shù)據(jù),因此不受影響;反之亦然。

常見(jiàn)的5種深拷貝方式(實(shí)戰(zhàn)必備)

Java中實(shí)現(xiàn)深拷貝的方式有多種,各自有優(yōu)缺點(diǎn),我們結(jié)合實(shí)例逐一講解,重點(diǎn)關(guān)注“用法+適用場(chǎng)景”,同時(shí)拆解最容易踩的坑。

① 構(gòu)造函數(shù)方式(簡(jiǎn)單但不推薦)

核心思路:通過(guò)new關(guān)鍵字創(chuàng)建新對(duì)象,在構(gòu)造函數(shù)中傳入原對(duì)象的所有屬性值,實(shí)現(xiàn)“值拷貝”。

// 改造User類,增加帶參構(gòu)造函數(shù)
public class User {
    private String username = "張三";
    private String password = "123456";
    // 帶參構(gòu)造函數(shù):傳入原對(duì)象,拷貝所有屬性值
    public User(User user) {
        this.username = user.username;
        this.password = user.password;
    }
    // 無(wú)參構(gòu)造函數(shù)(保留默認(rèn))
    public User() {}
    // getter/setter方法(省略,與前文一致)
}

測(cè)試代碼:

public static void main(String[] args) {
    // 原對(duì)象
    User user01 = new User();
    // 深拷貝:通過(guò)帶參構(gòu)造函數(shù)創(chuàng)建新對(duì)象
    User user02 = new User(user01);
    // 修改拷貝對(duì)象的屬性
    user02.setUsername("李四");
    user02.setPassword("654321");
    // 打印對(duì)比
    System.out.println("user01的username:" + user01.getUsername()); // 張三
    System.out.println("user02的username:" + user02.getUsername()); // 李四
    System.out.println("user01的password:" + user01.getPassword()); // 123456
    System.out.println("user02的password:" + user02.getPassword()); // 654321
}

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,無(wú)需依賴任何工具類,適合簡(jiǎn)單實(shí)體類(屬性少); 缺點(diǎn):當(dāng)對(duì)象屬性較多、層級(jí)較深(比如包含引用類型屬性、嵌套對(duì)象)時(shí),需要手動(dòng)在構(gòu)造函數(shù)中拷貝所有屬性,代碼冗余且易出錯(cuò);同時(shí)創(chuàng)建對(duì)象過(guò)多時(shí),會(huì)增加系統(tǒng)內(nèi)存開(kāi)銷,因此不推薦用于復(fù)雜場(chǎng)景

② 重寫clone()方法(重點(diǎn),但易踩坑)

Java中所有類都默認(rèn)繼承自O(shè)bject類,Object類中有一個(gè)native方法clone(),該方法的默認(rèn)實(shí)現(xiàn)是淺拷貝;我們可以通過(guò)“重寫clone()方法+實(shí)現(xiàn)Cloneable接口”,將其改造為深拷貝——但這里有一個(gè)極易踩的坑,下文會(huì)重點(diǎn)拆解。

步驟1:實(shí)現(xiàn)Cloneable接口,重寫clone()方法

Cloneable接口是一個(gè)“標(biāo)記接口”(空接口,沒(méi)有任何抽象方法),其作用是“告訴JVM:此類允許進(jìn)行拷貝操作”;如果不實(shí)現(xiàn)該接口,調(diào)用clone()方法會(huì)拋出CloneNotSupportedException異常。

/**
 * 重寫clone()方法實(shí)現(xiàn)深拷貝(初步改造)
 * 1. 實(shí)現(xiàn)Cloneable標(biāo)記接口
 * 2. 重寫Object類的clone()方法,修改訪問(wèn)權(quán)限為public
 * 3. 將返回值強(qiáng)轉(zhuǎn)為當(dāng)前類類型
 */
public class User implements Cloneable {
    private String username = "張三";
    private String password = "123456";
    // 重寫clone()方法
    @Override
    public User clone() throws CloneNotSupportedException {
        // 調(diào)用父類的clone()方法,強(qiáng)轉(zhuǎn)為User類型
        return (User) super.clone();
    }
    // getter/setter方法(省略,與前文一致)
}

步驟2:測(cè)試clone()方法的拷貝效果

public static void main(String[] args) {
    try {
        // 原對(duì)象
        User user01 = new User();
        // 深拷貝:調(diào)用重寫后的clone()方法
        User user02 = user01.clone();
        // 打印兩個(gè)對(duì)象的內(nèi)存地址(驗(yàn)證是否是不同對(duì)象)
        System.out.println("user01的內(nèi)存地址:" + user01);
        System.out.println("user02的內(nèi)存地址:" + user02);
        // 修改拷貝對(duì)象的屬性,驗(yàn)證是否影響原對(duì)象
        user02.setUsername("李四");
        System.out.println("-----------------------------------");
        System.out.println("user01的username:" + user01.getUsername()); // 張三
        System.out.println("user02的username:" + user02.getUsername()); // 李四
    } catch (CloneNotSupportedException e) {
        // 捕獲未實(shí)現(xiàn)Cloneable接口的異常
        e.printStackTrace();
    }
}

運(yùn)行結(jié)果與分析

user01的內(nèi)存地址:kaobei.User@15db9742
user02的內(nèi)存地址:kaobei.User@6d06d69c
-----------------------------------
user01的username:張三
user02的username:李四

結(jié)果符合預(yù)期: 1. 兩個(gè)對(duì)象的內(nèi)存地址不同(@后面的哈希值不同),說(shuō)明clone()方法創(chuàng)建了新的對(duì)象,實(shí)現(xiàn)了“值拷貝”; 2. 修改拷貝對(duì)象的username,原對(duì)象的username未變化,說(shuō)明兩者完全獨(dú)立,初步實(shí)現(xiàn)了深拷貝。

重點(diǎn)坑點(diǎn):clone()方法的“偽深拷貝”(必看)

上面的案例中,User類的屬性都是基本類型(String本質(zhì)是常量,也視為基本類型處理),因此重寫clone()方法能實(shí)現(xiàn)深拷貝;但如果User類中包含引用類型屬性(比如自定義對(duì)象),單純重寫clone()方法,就會(huì)變成“偽深拷貝”——僅拷貝引用類型的地址,不拷貝引用對(duì)象本身。

實(shí)戰(zhàn)演示:偽深拷貝的現(xiàn)象

步驟1:新增引用類型實(shí)體類Person

/**
 * 引用類型實(shí)體類:用于演示clone()方法的坑
 */
public class Person {
    private String name;
    // getter/setter方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

步驟2:修改User類,增加Person類型的引用屬性

public class User implements Cloneable {
    private String username = "張三";
    private String password = "123456";
    // 新增引用類型屬性:Person對(duì)象
    private Person person = new Person();
    // 新增方法:修改Person對(duì)象的name屬性
    public void changePersonName(String name) {
        this.person.setName(name);
    }
    // 新增方法:獲取Person對(duì)象的name屬性
    public String getPersonName() {
        return this.person.getName();
    }
    // 重寫的clone()方法(未修改)
    @Override
    public User clone() throws CloneNotSupportedException {
        return (User) super.clone();
    }
    // getter/setter方法(省略)
}

步驟3:測(cè)試clone()方法對(duì)引用類型的拷貝效果

public static void main(String[] args) {
    try {
        User user01 = new User();
        User user02 = user01.clone();
        // 打印兩個(gè)User對(duì)象的內(nèi)存地址(確認(rèn)是不同對(duì)象)
        System.out.println("user01的內(nèi)存地址:" + user01);
        System.out.println("user02的內(nèi)存地址:" + user02);
        // 修改原對(duì)象user01中的Person對(duì)象的name
        user01.changePersonName("李四");
        // 打印兩個(gè)User對(duì)象中Person的name
        System.out.println("-----------------------------------");
        System.out.println("user01的Person.name:" + user01.getPersonName());
        System.out.println("user02的Person.name:" + user02.getPersonName());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}

運(yùn)行結(jié)果與關(guān)鍵結(jié)論

user01的內(nèi)存地址:kaobei.User@15db9742
user02的內(nèi)存地址:kaobei.User@6d06d69c
-----------------------------------
user01的Person.name:李四
user02的Person.name:李四

驚人的現(xiàn)象:兩個(gè)User對(duì)象是獨(dú)立的(內(nèi)存地址不同),但它們內(nèi)部的Person對(duì)象卻相互影響——修改user01的Person.name,user02的Person.name也同步變化!

核心結(jié)論(必記):重寫clone()方法的默認(rèn)實(shí)現(xiàn),只能對(duì)當(dāng)前類的“基本類型屬性”進(jìn)行深拷貝,無(wú)法對(duì)“引用類型屬性”進(jìn)行深拷貝。也就是說(shuō),clone()方法會(huì)拷貝引用類型的地址,讓原對(duì)象和拷貝對(duì)象的引用屬性指向同一塊內(nèi)存地址,本質(zhì)上還是淺拷貝(偽深拷貝)。

解決方案:要實(shí)現(xiàn)真正的深拷貝,需要在clone()方法中,手動(dòng)對(duì)引用類型屬性也進(jìn)行clone()拷貝(遞歸clone),下文會(huì)補(bǔ)充完整實(shí)現(xiàn)。

③ Apache Commons Lang序列化(推薦,簡(jiǎn)潔高效)

Apache Commons Lang是Apache提供的工具類庫(kù),其中的SerializationUtils類提供了serialize()(序列化)和deserialize()(反序列化)方法,能快速實(shí)現(xiàn)深拷貝——核心原理是“將原對(duì)象序列化到字節(jié)流,再?gòu)淖止?jié)流反序列化為新對(duì)象”,反序列化會(huì)創(chuàng)建全新的對(duì)象,自然實(shí)現(xiàn)深拷貝。

使用步驟

1. 導(dǎo)入依賴(Maven):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

2. 讓實(shí)體類(包括引用類型)實(shí)現(xiàn)Serializable接口(序列化標(biāo)記接口,與Cloneable類似,無(wú)抽象方法):

// User類實(shí)現(xiàn)Serializable
public class User implements Serializable {
    private static final long serialVersionUID = 1L; // 序列化版本號(hào),避免反序列化異常
    private String username = "張三";
    private String password = "123456";
    private Person person = new Person(); // 引用類型,也需實(shí)現(xiàn)Serializable
    //  getter/setter、方法省略
}
// Person類實(shí)現(xiàn)Serializable
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    // getter/setter省略
}

3. 調(diào)用工具類方法實(shí)現(xiàn)深拷貝:

import org.apache.commons.lang3.SerializationUtils;
public static void main(String[] args) {
    User user01 = new User();
    // 深拷貝:序列化+反序列化
    User user02 = SerializationUtils.clone(user01);
    // 修改原對(duì)象的引用屬性
    user01.changePersonName("李四");
    // 驗(yàn)證:拷貝對(duì)象不受影響
    System.out.println("user01的Person.name:" + user01.getPersonName()); // 李四
    System.out.println("user02的Person.name:" + user02.getPersonName()); // null(初始值)
}

優(yōu)點(diǎn):無(wú)需手動(dòng)重寫clone()方法,無(wú)需遞歸處理引用類型,一行代碼實(shí)現(xiàn)深拷貝,支持任意層級(jí)的嵌套對(duì)象,簡(jiǎn)潔高效; 缺點(diǎn):需要導(dǎo)入第三方依賴(非JDK原生),且實(shí)體類及其所有引用類型都需實(shí)現(xiàn)Serializable接口,略繁瑣。

④ Gson序列化(推薦,無(wú)依賴限制)

Gson是Google提供的JSON解析工具類,也能通過(guò)“對(duì)象→JSON字符串→新對(duì)象”的方式實(shí)現(xiàn)深拷貝——核心原理是“將原對(duì)象轉(zhuǎn)為JSON字符串(脫離內(nèi)存引用),再將JSON字符串轉(zhuǎn)為新對(duì)象”,完全獨(dú)立于原對(duì)象。

使用步驟

1. 導(dǎo)入依賴(Maven):

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

2. 無(wú)需實(shí)現(xiàn)任何接口,直接調(diào)用方法:

import com.google.gson.Gson;
public static void main(String[] args) {
    Gson gson = new Gson();
    User user01 = new User();
    // 深拷貝:對(duì)象→JSON→新對(duì)象
    String json = gson.toJson(user01); // 原對(duì)象轉(zhuǎn)為JSON字符串
    User user02 = gson.fromJson(json, User.class); // JSON字符串轉(zhuǎn)為新對(duì)象
    // 修改原對(duì)象的屬性(包括引用類型)
    user01.setUsername("李四");
    user01.changePersonName("王五");
    // 驗(yàn)證:拷貝對(duì)象完全獨(dú)立
    System.out.println("user01的username:" + user01.getUsername()); // 李四
    System.out.println("user02的username:" + user02.getUsername()); // 張三
    System.out.println("user01的Person.name:" + user01.getPersonName()); // 王五
    System.out.println("user02的Person.name:" + user02.getPersonName()); // null
}

優(yōu)點(diǎn):無(wú)需實(shí)現(xiàn)Serializable或Cloneable接口,代碼簡(jiǎn)潔,支持復(fù)雜嵌套對(duì)象,且Gson是開(kāi)發(fā)中常用的JSON工具,無(wú)需額外引入多余依賴; 缺點(diǎn):序列化/反序列化過(guò)程會(huì)有一定的性能開(kāi)銷(比clone()方法慢),適合中小規(guī)模數(shù)據(jù)的拷貝場(chǎng)景。

⑤ Jackson序列化(推薦,Spring項(xiàng)目首選)

Jackson是Spring框架默認(rèn)的JSON解析工具,用法與Gson類似,也是通過(guò)“對(duì)象→JSON→新對(duì)象”實(shí)現(xiàn)深拷貝,適合Spring項(xiàng)目(無(wú)需額外導(dǎo)入依賴,Spring已集成)。

使用步驟

1. 導(dǎo)入依賴(Maven,Spring項(xiàng)目可省略):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

2. 調(diào)用Jackson工具類實(shí)現(xiàn)深拷貝:

import com.fasterxml.jackson.databind.ObjectMapper;
public static void main(String[] args) throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    User user01 = new User();
    // 深拷貝:對(duì)象→JSON字節(jié)流→新對(duì)象
    byte[] bytes = objectMapper.writeValueAsBytes(user01);
    User user02 = objectMapper.readValue(bytes, User.class);
    // 修改原對(duì)象,驗(yàn)證拷貝對(duì)象獨(dú)立性
    user01.setPassword("654321");
    user01.changePersonName("趙六");
    System.out.println("user01的password:" + user01.getPassword()); // 654321
    System.out.println("user02的password:" + user02.getPassword()); // 123456
    System.out.println("user01的Person.name:" + user01.getPersonName()); // 趙六
    System.out.println("user02的Person.name:" + user02.getPersonName()); // null
}

優(yōu)點(diǎn):Spring項(xiàng)目原生支持,無(wú)需額外導(dǎo)入依賴,性能優(yōu)于Gson,支持復(fù)雜對(duì)象和泛型,適合企業(yè)級(jí)開(kāi)發(fā); 缺點(diǎn):需要處理IO異常(writeValueAsBytes和readValue方法會(huì)拋出異常),代碼略繁瑣。

三、深拷貝方式對(duì)比與選型建議(實(shí)戰(zhàn)必備)

為了方便大家在實(shí)際開(kāi)發(fā)中快速選型,我們整理了5種深拷貝方式的優(yōu)缺點(diǎn)和適用場(chǎng)景,一目了然:

拷貝方式

優(yōu)點(diǎn)

缺點(diǎn)

適用場(chǎng)景

構(gòu)造函數(shù)

實(shí)現(xiàn)簡(jiǎn)單,無(wú)依賴

代碼冗余,易出錯(cuò),開(kāi)銷大

簡(jiǎn)單實(shí)體類(屬性少),臨時(shí)使用

重寫clone()方法

JDK原生,性能高

需實(shí)現(xiàn)Cloneable,引用類型需遞歸clone,易踩坑

性能要求高,對(duì)象層級(jí)簡(jiǎn)單

Apache Commons Lang

簡(jiǎn)潔高效,支持復(fù)雜對(duì)象

需導(dǎo)入第三方依賴,需實(shí)現(xiàn)Serializable

普通Java項(xiàng)目,復(fù)雜對(duì)象拷貝

Gson序列化

無(wú)接口要求,代碼簡(jiǎn)潔,常用依賴

性能一般,需導(dǎo)入Gson依賴

已有Gson依賴,中小規(guī)模數(shù)據(jù)拷貝

Jackson序列化

Spring原生支持,性能優(yōu),支持復(fù)雜對(duì)象

需處理異常,代碼略繁瑣

Spring Boot/Cloud項(xiàng)目,企業(yè)級(jí)開(kāi)發(fā)

四、全文核心總結(jié)(面試高頻考點(diǎn))

1. 淺拷貝拷貝地址,深拷貝拷貝數(shù)據(jù);淺拷貝共享底層資源,深拷貝完全獨(dú)立,這是兩者的核心區(qū)別;

2. Java中直接賦值是淺拷貝,new關(guān)鍵字+構(gòu)造函數(shù)、clone()、序列化等方式可實(shí)現(xiàn)深拷貝;

3. 重寫clone()方法易踩“偽深拷貝”坑——引用類型需遞歸clone,否則僅拷貝引用地址;

4. 實(shí)際開(kāi)發(fā)中,優(yōu)先選擇Gson/Jackson序列化(Spring項(xiàng)目選Jackson)或Apache Commons Lang,兼顧簡(jiǎn)潔性和實(shí)用性;

5. 無(wú)需數(shù)據(jù)隔離時(shí),淺拷貝更高效;需要數(shù)據(jù)隔離(如多線程、數(shù)據(jù)修改)時(shí),必須使用深拷貝,避免出現(xiàn)數(shù)據(jù)安全問(wèn)題。

最后提醒:拷貝操作的核心是“數(shù)據(jù)隔離”,選擇哪種方式,關(guān)鍵看“對(duì)象復(fù)雜度、性能要求、項(xiàng)目依賴”——理解了淺拷貝和深拷貝的本質(zhì),無(wú)論遇到哪種場(chǎng)景,都能快速選型、避免踩坑。

到此這篇關(guān)于Java拷貝之一文徹底分清淺拷貝與深拷貝的文章就介紹到這了,更多相關(guān)java淺拷貝與深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

江油市| 图木舒克市| 嘉黎县| 易门县| 岚皋县| 六安市| 江山市| 景宁| 丰镇市| 东光县| 元江| 江源县| 西宁市| 高清| 仁布县| 德保县| 泾阳县| 子洲县| 连江县| 名山县| 芦山县| 杭锦后旗| 革吉县| 常德市| 盐池县| 浦东新区| 台前县| 乌鲁木齐县| 澄江县| 乃东县| 澄城县| 曲沃县| 周宁县| 辰溪县| 荆州市| 阳谷县| 林州市| 巧家县| 宝兴县| 巨野县| 仲巴县|