詳解Java深拷貝,淺拷貝和Cloneable接口
1. Cloneable接口的介紹
Cloneable是標記型的接口(空接口),它們內(nèi)部都沒有方法和屬性,實現(xiàn) Cloneable來表示該對象能被克隆,能使用Object.clone()方法。如果沒有實現(xiàn) Cloneable的類對象調(diào)用clone()就會拋出CloneNotSupportedException異常。

可以理解為Cloneable接口發(fā)揮的是標記功能,自定義類型需要用戶自己標記出哪些類是可以clone的,這個標記就是去實現(xiàn)Cloneable接口,實現(xiàn)了Cloneable接口后就表明該類創(chuàng)建的對象可以被克隆。
而要想使一個類具備拷貝實例的功能,除了要實現(xiàn)Cloneable接口,還必須重寫Object類的clone()方法。

可以看到Object類的clone()方法是被protected修飾的,所以需要在重寫的clone()方法中通過super關(guān)鍵字去調(diào)用Object類中的clone()方法

2. 淺拷貝的介紹和實例
在拷貝一個對象時,對 對象的基本數(shù)據(jù)類型的成員變量進行拷貝,但對引用類型的成員變量只進行引用的傳遞,并沒有創(chuàng)建一個新的對象,當對引用類型的內(nèi)容修改會影響被拷貝的對象。簡而言之:淺拷貝僅僅復(fù)制所拷貝的對象,而不復(fù)制它所引用的對象。
觀察下面的代碼,將Money類的實例作為了Person類的字段,new一個Person類的對象person1,將這個person1對象拷貝到person2中,這里的拷貝就是淺拷貝了,只是將person1對象的money引用拷貝到了person2,person1和person2中的momey指向的是同一個對象。
class Money {
public double m = 666;
}
class Person implements Cloneable{
int id;
public Money money = new Money();
public Person(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", money=" + money.m +
'}';
}
}
public class TestDemo3 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(1);
Person person2 = (Person) person1.clone();
System.out.println("通過person2修改前的結(jié)果");
System.out.println(person1);
System.out.println(person2);
person2.money.m = 888;
person2.id = 2;
System.out.println("通過person2修改后的結(jié)果");
System.out.println(person1);
System.out.println(person2);
}
}
執(zhí)行結(jié)果:

淺拷貝圖解:

3. 深拷貝的介紹和實例
在拷貝一個對象時,除了對基本數(shù)據(jù)類型的成員變量進行拷貝,對引用類型的成員變量進行拷貝時,創(chuàng)建一個新的對象來保存引用類型的成員變量。簡而言之:深拷貝把要復(fù)制的對象所引用的對象都復(fù)制了一遍。
下面的代碼實現(xiàn)了深拷貝;實現(xiàn)person1對象的深拷貝,先用Person tmp引用來保存淺拷貝的結(jié)果,通過tmp引用找到money對象,再將money對象拷貝一份,然后賦值給tmp中的money,最后返回tmp即可。這樣就將money引用的對象也拷貝了一份,實現(xiàn)了深拷貝,此時person1和person2中的momey指向的是兩個不同的對象。
class Money implements Cloneable{
public double m = 666;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int id;
public Money money = new Money();
public Person(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//return super.clone();
Person tmp = (Person) super.clone();
tmp.money = (Money) this.money.clone();
return tmp;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", money=" + money.m +
'}';
}
}
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException{
Person person1 = new Person(1);
Person person2 = (Person) person1.clone();
System.out.println("通過person2修改前的結(jié)果");
System.out.println(person1);
System.out.println(person2);
person2.money.m = 888;
person2.id = 2;
System.out.println("通過person2修改后的結(jié)果");
System.out.println(person1);
System.out.println(person2);
}
}
執(zhí)行結(jié)果:

深拷貝圖解:

4. clone方法總結(jié)
java中clone方法是一個淺拷貝,引用類型依然在傳遞引用。我們可以通過繼續(xù)調(diào)用clone()方法,對 該對象的引用類型變量再實現(xiàn)一次clone()的方法來實現(xiàn)深拷貝。
到此這篇關(guān)于詳解Java深拷貝,淺拷貝和Cloneable接口的文章就介紹到這了,更多相關(guān)Java Cloneable接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WebUploader+SpringMVC實現(xiàn)文件上傳功能
WebUploader是由Baidu團隊開發(fā)的一個簡單的以HTML5為主,F(xiàn)LASH為輔的現(xiàn)代文件上傳組件。這篇文章主要介紹了WebUploader+SpringMVC實現(xiàn)文件上傳功能,需要的朋友可以參考下2017-06-06
詳解SpringBoot+Mybatis實現(xiàn)動態(tài)數(shù)據(jù)源切換
這篇文章主要介紹了詳解SpringBoot+Mybatis實現(xiàn)動態(tài)數(shù)據(jù)源切換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05
hibernate一對多關(guān)聯(lián)映射學習小結(jié)
這篇文章主要介紹了hibernate一對多關(guān)聯(lián)映射學習小結(jié),需要的朋友可以參考下2017-09-09
Spring項目使用Maven和BCrypt實現(xiàn)修改密碼功能方式
在數(shù)字時代,信息安全尤其是密碼安全至關(guān)重要,本文通過實例探討如何在Spring項目中利用Maven和BCrypt實現(xiàn)一個安全的密碼修改功能,我們將從環(huán)境搭建到編寫核心業(yè)務(wù)邏輯,再到完成功能測試,確保每一步都遵循最佳安全實踐,通過本文,你將了解到密碼安全的重要性2024-10-10
Spring報錯:Error creating bean with name的問
這篇文章主要介紹了Spring報錯:Error creating bean with name的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Java調(diào)用Python腳本實現(xiàn)HelloWorld的示例詳解
作為程序員,我們經(jīng)常會遇到需要在Java項目中調(diào)用Python腳本的場景,下面我們來看看如何從基礎(chǔ)到進階,一步步實現(xiàn)Java與Python的"HelloWorld"交互吧2025-08-08

