目錄
一.Clonable接口
實現步驟:
完整代碼:
?二.深拷貝
實現步驟:
完整代碼:
淺拷貝與深拷貝的對比
使用場景建議
完
?淺拷貝(Shallow Copy)和深拷貝(Deep Copy)是對象復制的兩種方式,主要區別在于對對象內部引用類型字段的處理方式不同。
- 淺拷貝:僅復制對象本身及其基本類型字段的值,對于引用類型字段,復制的是引用地址(即新對象和原對象共享同一塊內存)。
- 深拷貝:完全復制對象及其所有字段(包括引用類型字段),新對象與原對象不共享任何內存,彼此獨立。
?一.Clonable接口
實現步驟:
①創建兩個類
public class Test1 {public static void main(String[] args) {Person person1 = new Person(10,"zhangsan");//Person person2 = person1.clone();//最開始點不出來}
}
public class Person {public int age;public String name;public Person(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +'}';}
}
②通過 person1 調用 Object類 的 clone 方法 會失敗
③重寫 Object類 的 clone 方法
( Alt+Insert? → Generate → Override Methods → clone() )
④調用 重寫 的 clone 方法 的返回值是Object類型,需要強轉為(Person)
⑤現在運行會有一個異常
解決方法:
- throws CloneNotSupportedException? ( 該內容在重寫的clone()方法中 )?
- 復制到main方法的后面
⑥現在代碼雖然不會報錯,但是還會有異常(不支持克隆)
解決方法:在person類 后面加上一個接口(標記接口)
完整代碼:
public class Person implements Cloneable {public int age;public String name;public Person(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +'}';}@Overrideprotected Object clone()throws CloneNotSupportedException {return super.clone();}
}
public class Test1 {public static void main(String[] args)throws CloneNotSupportedException {Person person1 = new Person(10,"zhangsan");Person person2 = (Person) person1.clone();//最開始點不出來}
}
?二.深拷貝
實現步驟:
①創建一個類,包含 Clonable接口 和 clone() 方法
public class Money implements Cloneable{public double money = 9.9;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
并且在Person類中實例一個 Money對象 :m?
原理:
- 通過改變 person2.m.money ,看 person1.m.money 是否被修改?
- 如果改變 person2.m.money ,person1.m.money也被修改,那么就是淺拷貝,反之則為深拷貝
②再次重寫Person類中的clone()?方法
protected Object clone()throws CloneNotSupportedException {//return super.clone();Person tmp = (Person) super.clone();tmp.m = (Money) this.m.clone();return tmp;}
③進行調試
public class Test1 {public static void main(String[] args)throws CloneNotSupportedException {Person person1 = new Person(10,"zhangsan");Person person2 = (Person) person1.clone();//最開始點不出來System.out.println("修改前:"+person1.m.money);System.out.println("修改前:"+person2.m.money);person2.m.money = 99.99;System.out.println("修改后:"+person1.m.money);System.out.println("修改后:"+person2.m.money);}
}
完整代碼:
public class Test1 {public static void main(String[] args)throws CloneNotSupportedException {Person person1 = new Person(10,"zhangsan");Person person2 = (Person) person1.clone();//最開始點不出來System.out.println("修改前:"+person1.m.money);System.out.println("修改前:"+person2.m.money);person2.m.money = 99.99;System.out.println("修改后:"+person1.m.money);System.out.println("修改后:"+person2.m.money);}
}
public class Person implements Cloneable {public int age;public String name;public Money m = new Money();public Person(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +'}';}@Overrideprotected Object clone()throws CloneNotSupportedException {//return super.clone();Person tmp = (Person) super.clone();tmp.m = (Money) this.m.clone();return tmp;}
}
public class Money implements Cloneable{public double money = 9.9;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
淺拷貝與深拷貝的對比
特性 | 淺拷貝 | 深拷貝 |
---|---|---|
復制范圍 | 僅復制對象本身和基本類型字段 | 復制對象及其所有引用類型字段 |
內存占用 | 低(共享引用類型字段) | 高(完全獨立) |
修改影響 | 修改引用類型字段會影響原對象 | 修改引用類型字段不影響原對象 |
實現復雜度 | 簡單 | 復雜(需遞歸處理引用類型) |
使用場景建議
- 淺拷貝:適用于對象內部沒有引用類型字段,或引用類型字段不可變(如
String
)。 - 深拷貝:適用于對象內部有可變引用類型字段,且需要完全獨立副本的場景(如緩存、狀態快照等)