一文深入理解Java中的深拷貝機(jī)制
一、深拷貝和淺拷貝的概念
深拷貝(Deep Copy)和淺拷貝(Shallow Copy)是指在進(jìn)行對(duì)象復(fù)制時(shí)所產(chǎn)生的兩種不同結(jié)果。
淺拷貝:淺拷貝是指創(chuàng)建一個(gè)新對(duì)象,然后將原始對(duì)象的非靜態(tài)字段的值復(fù)制到新對(duì)象。新對(duì)象和原始對(duì)象共享引用類(lèi)型的成員變量。簡(jiǎn)而言之,淺拷貝只復(fù)制對(duì)象的引用,而不復(fù)制引用指向的內(nèi)容。
深拷貝:深拷貝是指創(chuàng)建一個(gè)新對(duì)象,然后遞歸地復(fù)制原始對(duì)象的所有成員變量,包括引用類(lèi)型的成員變量和基本類(lèi)型的成員變量。深拷貝得到的新對(duì)象與原始對(duì)象完全獨(dú)立,修改新對(duì)象不會(huì)影響原始對(duì)象。
接下來(lái),我們將介紹三種常見(jiàn)的實(shí)現(xiàn)深拷貝的方法。
二、使用Cloneable接口與重寫(xiě)clone()方法
Java中的Object類(lèi)提供了一個(gè)名為clone()的方法,用于實(shí)現(xiàn)對(duì)象拷貝。為了使用該方法進(jìn)行深拷貝,需要滿(mǎn)足兩個(gè)條件:
- 類(lèi)實(shí)現(xiàn)
Cloneable接口,將其標(biāo)記為可以拷貝的。 - 重寫(xiě)
clone()方法,在方法中通過(guò)遞歸調(diào)用clone()來(lái)復(fù)制對(duì)象引用。
示例代碼如下:
public class MyClass implements Cloneable {
private int number;
private List<String> list;
MyClass() {
this.number = 0;
this.list = new ArrayList<>();
}
MyClass(int number) {
this.number = number;
this.list = new ArrayList<>();
}
void setNumber(int number) {
this.number = number;
}
int getNumber() {
return number;
}
@Override
public MyClass clone() throws CloneNotSupportedException {
MyClass copy = (MyClass) super.clone();
copy.list = new ArrayList<>(this.list); // 進(jìn)行深拷貝
return copy;
}
}
public class Main{
public static void main(String[] args) throws CloneNotSupportedException {
MyClass myClass1 = new MyClass(3);
MyClass myClass2 = myClass1.clone();
myClass1.setNumber(2);
System.out.println(myClass2.getNumber()); // 3
}
}三、使用序列化與反序列化
Java中的序列化(Serialization)機(jī)制可以將一個(gè)對(duì)象轉(zhuǎn)換為字節(jié)流,而反序列化(Deserialization)則可以將字節(jié)流還原為對(duì)象。利用這一機(jī)制,我們可以實(shí)現(xiàn)深拷貝。
示例代碼如下:
public class MyClass implements Serializable {
private int number;
private List<String> list;
MyClass() {
this.number = 0;
this.list = new ArrayList<>();
}
MyClass(int number) {
this.number = number;
this.list = new ArrayList<>();
}
void setNumber(int number) {
this.number = number;
}
int getNumber() {
return number;
}
public MyClass deepCopy() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (MyClass) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
public class Main{
public static void main(String[] args) throws CloneNotSupportedException {
MyClass myClass1 = new MyClass(3);
MyClass myClass2 = myClass1.deepCopy();
myClass1.setNumber(2);
System.out.println(myClass2.getNumber()); // 3
}
}四、使用第三方庫(kù)
除了自己手動(dòng)實(shí)現(xiàn)深拷貝外,還可以使用一些優(yōu)秀的第三方庫(kù)來(lái)簡(jiǎn)化深拷貝的過(guò)程。例如,Apache Commons和Google Guava等庫(kù)都提供了一些工具方法來(lái)實(shí)現(xiàn)深拷貝。
五、總結(jié)
深拷貝和淺拷貝在Java中是常見(jiàn)的操作,深拷貝復(fù)制對(duì)象以及其引用的所有子對(duì)象,而淺拷貝只復(fù)制對(duì)象本身。根據(jù)具體的需求和場(chǎng)景選擇使用深拷貝還是淺拷貝非常重要,熟練掌握深拷貝和淺拷貝的概念和實(shí)現(xiàn)方法,對(duì)編寫(xiě)高效、安全的Java代碼具有重要意義。
到此這篇關(guān)于一文深入理解Java中的深拷貝機(jī)制的文章就介紹到這了,更多相關(guān)Java深拷貝機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java.lang.StackOverflowError出現(xiàn)的原因及解決
這篇文章主要介紹了java.lang.StackOverflowError出現(xiàn)的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
使用Spring AOP做接口權(quán)限校驗(yàn)和日志記錄
本文介紹了面向切面編程(AOP)的基本概念、應(yīng)用場(chǎng)景及其在Spring中的實(shí)現(xiàn)原理,通過(guò)AOP,可以方便地在不修改原有代碼的情況下,實(shí)現(xiàn)日志記錄、權(quán)限校驗(yàn)等功能,以學(xué)生身份證號(hào)查詢(xún)接口為例,展示了如何定義權(quán)限注解、切面類(lèi)以及權(quán)限驗(yàn)證服務(wù),感興趣的朋友一起看看吧2025-01-01
利用Java代碼寫(xiě)一個(gè)并行調(diào)用模板
這篇文章主要介紹了利用Java代碼寫(xiě)一個(gè)并行調(diào)用模板,文章基于Java的相關(guān)內(nèi)容展開(kāi)寫(xiě)一個(gè)并行調(diào)用模板的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05

