public class Student implements Cloneable {
public Student clone() {
Student clonedStudent = (Student) super.clone();
return clonedStudent;
}
}
爲什麼Java返回學生對象而不是返回對象類對象。因爲我們正在使用超級。這是否意味着Java本身在克隆方法中提供了淺層克隆?Java克隆方法如何工作?
public class Student implements Cloneable {
public Student clone() {
Student clonedStudent = (Student) super.clone();
return clonedStudent;
}
}
爲什麼Java返回學生對象而不是返回對象類對象。因爲我們正在使用超級。這是否意味着Java本身在克隆方法中提供了淺層克隆?Java克隆方法如何工作?
java克隆是field by field copy
即,因爲Object類不知道將調用clone()方法的類的結構。
1)如果類具有只有原始數據類型成員那麼對象的一個完全新副本將被創建並在參考新對象副本將被歸還。
2)如果類包含任何類型然後只對這些成員的對象引用被複制的成員,並因此在兩個原始對象的構件的引用以及克隆的對象指的是同一物體 。
請參考以下鏈接object cloning in java
從Object
Acording到String javadocclone()
產生,它從調用對象的「淺」副本。
如果您正在實施clone()
,則約定是您從super.clone()
獲得初始副本,然後實施克隆操作的其餘部分以修改此返回的對象。
clone()
方法的作用類似於複製構造函數。
它創建並返回對象的副本。 由於對象類有克隆方法(保護),您不能在所有類中使用它。你想克隆的類應該實現克隆方法並覆蓋它。它應該爲複製提供自己的意思,或者至少應該調用super.clone()
。你也必須實現Cloneable標記接口,否則你將得到CloneNotSupportedException。當你調用super.clone()
時,你依賴於Object類的實現,你得到的是一個淺拷貝。
您可以通過Wiki Page瞭解更多。
對於克隆對象應該實現接口Cloneable
如果你要使用克隆方法的一類,其中Cloneable
接口沒有實現,它拋出CloneNotSupportedException
。
java.lang.Object提供了Java中clone()方法的默認實現。它在Object類中聲明爲protected和native,所以在本機代碼中實現。由於它的約定是通過調用super.clone()方法來返回對象的clone(),所以任何克隆過程最終都會到達java.lang.Object的clone()方法。這個方法首先檢查相應的對象是否實現Cloneable接口,它是一個標記接口。如果該實例沒有實現Cloneable,那麼它會在Java中引發CloneNotSupportedException,這是一個檢查異常,在克隆對象時總是需要處理該異常。 在java中,如果一個類需要支持克隆,它必須執行以下操作:
A)您必須實現Cloneable接口。 B)您必須從Object類重寫clone()方法。 [有點奇怪。 clone()方法應該已經在Cloneable接口中。]
關於clone()方法的Java文檔在下面給出(格式化和提取)。 /* 創建並返回此對象的副本。 「複製」的確切含義可能取決於對象的類別。 一般意圖是,對於任何對象x,表達式: 1)x.clone()!= x將爲true //保證克隆的對象將具有單獨的內存地址分配。 2)x.clone()。getClass()== x.getClass()將是true,但這些並不是絕對的要求。原始的和克隆的對象應該有相同的類類型,但它不是強制性的。 3)x.clone()。equals(x)將爲真,這不是絕對的要求。原始和克隆的對象應該使用equals()方法相等,但它不是強制性的。 */
讓我們看一個例子:
public class MyClone {
int x;
public static void main(String[] args) throws
CloneNotSupportedException {
MyClone c = new MyClone();
MyClone a = (MyClone) c.clone(); // Type-cast is required
}
}
因爲克隆()是Object類的一部分,而對象將不實現Cloneable接口,當我們自己的類不會實現Cloneable接口,JVM不會知道這個類有資格克隆,所以CloneNotSupportedException就出來了。
只有兩個東西,當我們說一個MyClone =(MyClone)c.clone();:
它要麼將返回克隆的對象是可能的。
或者它會拋出CloneNotSupportedException。
因爲很明顯,當你想克隆對象的時候,你的類中實現clone()不是必須的,如果你不需要,Object中的clone()方法被聲明爲protected - 只有子類和成員相同的包將能夠在對象上調用clone()。如果你想改變它,你應該覆蓋它並公開。的clone()方法調用之前
檢查:
if(c instanceof Cloneable) {
MyClone a = (MyClone) c.clone();
}
注:當克隆()被調用構造函數沒有被調用。我們有責任正確設置該類的所有成員變量。
實施
Room.java
public class Room {
private String roomSize;
public Room(String roomSize){
this.roomSize = roomSize;
}
//Any Getters-Setters goes here
}
Flat.java
public class Flat implements Cloneable {
private String flatNumber;
private Room room;
public Flat(String size,Room room){
this.size = size;
this.room = room;
}
public Object clone() {
try {
return (Flat)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
}
//Any Getters-Setters goes here
}
Main.java
public class Main {
public static void main(String[] args) {
Room room = new Room("40 X 40");
Flat flat1 = new Flat(403 , room);
Flat flat2 = (Flat)flat1.clone();
}
}
這裏super.clone()來獲取調用內部的clone()。我們知道,clone()是在Object中聲明的,所以它被每個Java對象繼承。調用super.clone()複製我們的超類的字段,並按字段複製字段。這就是所謂的淺拷貝,意思是當你使用clone()複製Flat時,該字段的flatNumber將被複製爲各自的值,但房間通過引用逐位複製 - 內存地址將被複制。
您對原始對象的空間進行的任何更改都會反映在克隆的對象中,反之亦然。爲了解決這個問題,我們需要深度複製。現在,我們需要更改Room類以及實現「Cloneable」接口和clone()方法,然後在Flat對象的clone()方法內調用Room對象的clone()方法。
新的實施
Room.java
public class Room {
private String roomSize;
public Room(String roomSize){
this.roomSize = roomSize;
}
public Object clone() {
try {
return (Room)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
}
//Any Getters-Setters goes here
}
Flat.java
public class Flat implements Cloneable {
private String flatNumber;
private Room room;
public Flat(String size,Room room){
this.size = size;
this.room = room;
}
public Object clone() {
Flat flat = null;
try {
flat = (Flat)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
flat.room = (Room) room.clone();
return flat;
}
//Any Getters-Setters goes here
}
Main.java
public class Main {
public static void main(String[] args) {
Room room = new Room("40 X 40");
Flat flat1 = new Flat(403, room);
Flat flat2 = (Flat)flat1.clone();
}
}
我希望這將提供一個更好地瞭解克隆及其執行情況。
由於http://interviewguess.blogspot.in/2017/02/how-does-clone-method-work.html
不要你http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29明白什麼?你讀過這個javadoc嗎?它詳細解釋了clone()如何工作。 –