一文深入理解Java中的深拷貝機(jī)制
一、深拷貝和淺拷貝的概念
深拷貝(Deep Copy)和淺拷貝(Shallow Copy)是指在進(jìn)行對象復(fù)制時(shí)所產(chǎn)生的兩種不同結(jié)果。
淺拷貝:淺拷貝是指創(chuàng)建一個(gè)新對象,然后將原始對象的非靜態(tài)字段的值復(fù)制到新對象。新對象和原始對象共享引用類型的成員變量。簡而言之,淺拷貝只復(fù)制對象的引用,而不復(fù)制引用指向的內(nèi)容。
深拷貝:深拷貝是指創(chuàng)建一個(gè)新對象,然后遞歸地復(fù)制原始對象的所有成員變量,包括引用類型的成員變量和基本類型的成員變量。深拷貝得到的新對象與原始對象完全獨(dú)立,修改新對象不會影響原始對象。
接下來,我們將介紹三種常見的實(shí)現(xiàn)深拷貝的方法。
二、使用Cloneable接口與重寫clone()方法
Java中的Object類提供了一個(gè)名為clone()
的方法,用于實(shí)現(xiàn)對象拷貝。為了使用該方法進(jìn)行深拷貝,需要滿足兩個(gè)條件:
- 類實(shí)現(xiàn)
Cloneable
接口,將其標(biāo)記為可以拷貝的。 - 重寫
clone()
方法,在方法中通過遞歸調(diào)用clone()
來復(fù)制對象引用。
示例代碼如下:
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è)對象轉(zhuǎn)換為字節(jié)流,而反序列化(Deserialization)則可以將字節(jié)流還原為對象。利用這一機(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 } }
四、使用第三方庫
除了自己手動實(shí)現(xiàn)深拷貝外,還可以使用一些優(yōu)秀的第三方庫來簡化深拷貝的過程。例如,Apache Commons和Google Guava等庫都提供了一些工具方法來實(shí)現(xiàn)深拷貝。
五、總結(jié)
深拷貝和淺拷貝在Java中是常見的操作,深拷貝復(fù)制對象以及其引用的所有子對象,而淺拷貝只復(fù)制對象本身。根據(jù)具體的需求和場景選擇使用深拷貝還是淺拷貝非常重要,熟練掌握深拷貝和淺拷貝的概念和實(shí)現(xiàn)方法,對編寫高效、安全的Java代碼具有重要意義。
到此這篇關(guān)于一文深入理解Java中的深拷貝機(jī)制的文章就介紹到這了,更多相關(guān)Java深拷貝機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java.lang.StackOverflowError出現(xiàn)的原因及解決
這篇文章主要介紹了java.lang.StackOverflowError出現(xiàn)的原因及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07使用Spring AOP做接口權(quán)限校驗(yàn)和日志記錄
本文介紹了面向切面編程(AOP)的基本概念、應(yīng)用場景及其在Spring中的實(shí)現(xiàn)原理,通過AOP,可以方便地在不修改原有代碼的情況下,實(shí)現(xiàn)日志記錄、權(quán)限校驗(yàn)等功能,以學(xué)生身份證號查詢接口為例,展示了如何定義權(quán)限注解、切面類以及權(quán)限驗(yàn)證服務(wù),感興趣的朋友一起看看吧2025-01-01