深拷貝與淺拷貝
淺拷貝
public class Student implements Cloneable{
Integer a;
Integer b;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
String c;
Student child;
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student();
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.child == s2.child);
}
}
/**********************************************************************/
false
true
由上述程式碼及執行結果我們可以看出,呼叫clone方法之後,確實s2是一個新的物件,記憶體地址已經發生了改變,但s和s2的child屬性仍然指向相同的地址,這便是淺拷貝,當然8種基本資料型別是深拷貝,String則是例外。
深拷貝
public class Teacher implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable{
Integer a;
Integer b;
public Student(Teacher t) {
this.t = t;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student s = (Student) super.clone();
s.t = (Teacher)s.t.clone();//徹底深拷貝關鍵
return s;
}
String c;
Teacher t;
}
public class IntersectionofTwoArraysII {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher t = new Teacher();
Student s = new Student(t);
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.t == s2.t);
}
}
/**********************************************************************/
false
false
如上程式碼執行結果所示為深拷貝,想要實現深拷貝,就需要在重寫Cloneable介面的clone()方法,並呼叫屬性的clone()方法,因此關聯類也要實現Cloneable介面,從而形成拷貝鏈,實現徹底深拷貝。
實現徹底的深拷貝並不容易,因為它要求涉及的所有類都實現了cloneable介面,但是如StringBuffer由於其沒有實現Cloneable介面,想要實現深拷貝效果,則需要做特殊處理從而實現深拷貝的效果。可以在clone方法中實現
sb=new StringBuffer(sb.toString());
Cloneable介面
Cloneable其實就是一個標記介面,只有實現這個介面後,然後在類中重寫Object中的clone方法,然後通過類呼叫clone方法才能克隆成功,如果不實現Cloneable其實就是一個標記介面介面,呼叫clone方法則會丟擲CloneNotSupportedException(克隆不被支援)異常。
如何判斷類是否實現了cloneable介面呢?
/**
* Creates and returns a copy of this {@code Object}. The default
* implementation returns a so-called "shallow" copy: It creates a new
* instance of the same class and then copies the field values (including
* object references) from this instance to the new instance. A "deep" copy,
* in contrast, would also recursively clone nested objects. A subclass that
* needs to implement this kind of cloning should call {@code super.clone()}
* to create the new instance and then create deep copies of the nested,
* mutable objects.
*
* @return a copy of this object.
* @throws CloneNotSupportedException
* if this object's class does not implement the {@code
* Cloneable} interface.
*/
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class doesn't implement Cloneable");
}
return internalClone((Cloneable) this);
}
/*
* Native helper method for cloning.
*/
private native Object internalClone(Cloneable o);
clone方法首先會判物件是否實現了Cloneable介面,若無則丟擲CloneNotSupportedException, 最後會呼叫internalClone. intervalClone是一個native方法,一般來說native方法的執行效率高於非native方法。