一、克隆的原理與應用
clone在堆上分配內存,分配的內存和源對象(即調用clone方法的對象)相同,然后再使用原對象中對應的各個域,填充新對象的域, 填充完成之后,clone方法返回,一個新的相同的對象被創建,同樣可以把這個新對象的引用發布到外部。如果,想要對該對象進行處理,又想保留原來數據進行接下來的操作,clone就很方便。
二、克隆的實現
1、被克隆的類必須自己實現Cloneable 接口,以指示 Object.clone() 方法可以合法地對該類實例進行按字段復制。Cloneable 接口實際上是個標識接口,沒有任何接口方法。
2、覆蓋Object.clone()方法。
三、淺拷貝與深拷貝
淺拷貝:在填充新對象域的時候,進行簡單的字段賦值。
深拷貝:按照慣例,此方法返回的對象應該獨立於該對象(正被復制的對象)。要獲得此獨立性,在 super.clone 返回對象之前,有必要對該對象的一個或多個字段進行修改。這通常意味着要復制包含正在被復制對象的內部“深層結構”的所有可變對象,並使用對副本的引用替換對這些對象的引用。如果一個類只包含基本字段或對不變對象的引用,那么通常不需要修改 super.clone 返回的對象中的字段。(簡單來說,就是將該對象內部的對象也克隆一份,而不是簡單的引用賦值)
(可變對象:對象創建后字段值可以改變)
淺拷貝:
class Head { String s; void set(String s1) { s = s1; } } public class Person implements Cloneable{ Head head; Person(Head head) { this.head = head; } protected Object clone() throws CloneNotSupportedException{ return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException{ Person p = new Person(new Head()); Person p1 = (Person)p.clone(); System.out.println("p == p1 " + (p == p1)); System.out.println("p.head == p1.head " + (p.head == p1.head)); } }
輸出結果:
p == p1 false
p.head == p1.head true
結果分析:
可以從結果過中看到,克隆創建了一個新的Person對象,但是p.head與p1.head仍然指向同一對象,也就是說p與p1仍然存在聯系,這是我們不想看到的。
深拷貝:
class Head implements Cloneable{ String s; void set(String s1) { s = s1; } protected Object clone() throws CloneNotSupportedException{ return super.clone(); } } public class Person implements Cloneable{ Head head; Person(Head head) { this.head = head; } protected Object clone() throws CloneNotSupportedException{ Person p = (Person)super.clone(); p.head = (Head)head.clone(); return p; } public static void main(String[] args) throws CloneNotSupportedException{ Person p = new Person(new Head()); Person p1 = (Person)p.clone(); System.out.println("p == p1 " + (p == p1)); System.out.println("p.head == p1.head " + (p.head == p1.head)); } }
輸出結果:
p == p1 false
p.head == p1.head false
結果分析:要實現深層拷貝要將對象內部的對象拷貝。
好文推薦:詳解Java中的clone方法