Java&&Clone之淺拷貝和深拷貝

1.Object類中有clone方法,但是Object又沒有實現Cloneable接口,這是為什麼?對於一個沒有實現cloneable的類來説,還可以用從Object類繼承而來的clone方法實現一些基本的值的複製操作,那是不是可以説clone方法並沒有對對象是否屬於Cloneable類型進行檢驗?

Object類的clone是protected的( protected Object clone () throws CloneNotSupportedException),不能直接調用,可以被子類調用。Object類的clone會知道對象大小,為它分配足夠的內存空間,並將舊對象的內容複製到新的對象中。但是Object.clone()執行其動作之前必須先檢查class是否實現了Cloneable接口。
Cloneable接口是一個標記接口,也就是沒有任何內容,定義如下。
package java.lang;
public interface Cloneable{
}
這裏分析一下這接口的用法。
java中clone的含義是,假設X是一個非空對象,則:
1.x.clone() != x 為true,就是説它們不是同一個對象;
2.x.clone().getClass() == x.getClass()為true,説明它們是同一個類型class;
3.x.equals(x.clone())為true,説明邏輯上應當相當。

clone方法是在Object中定義的,而且是protected類型的,只有實現了這個接口,才可以在該類的實例上調用clone方法,否則會拋出   CloneNotSupportedException
Object中默認的實現是一個淺複製,也就是表面複製,如果需要實現深層次的複製,必須對類中可變域生成新的實例。
public class Unsupported{
	public Object clone(){
		Object obj;
		try{
			obj = supper.clone();
		}catch(CloneNotSupportedException ex){
			ex.printStackTrace();
		}
		return obj;
	}
}
加上implements Cloneable就可以了。當然也可以不實現這個接口,但是覆蓋clone方法,其代碼如下:
public class Unnormal{
	public Object clone(){
		return new Unnormal();
	}
}
這樣肯定沒問題的,不過已經和java中的clone機制沒有關係了。
下面舉一個例子説明淺複製和深複製。
public class ShallowCopy implements Cloneable{
	private Date begin;
	public Date getBegin(){return this.begin;}
	public void setBegin(Date d){this.begin=d;}
	public Object clone(){
		Object obj = null;
		try{
			obj=super.clone();
		}catch(CloneNotSupportedException ex){
			ex.printStackTrace();
		}
		return obj;
	}
}

public class DeepCopy implements Cloneable{
	private Date begin;
	public Date getBegin(){return this.begin;}
	public void setBegin(Date d){this.begin=d;}
	public Object clone(){
		DeepCopy obj = null;
		try{
			obj = (DeepCopy)super.clone();
		}catch(CloneNotSupportedException ex){
			ex.printStackTrace();
		}
		obj.setBegin((Date)this.getBegin().clone());
		return obj;
	}
}

總結:
clone方法是在Object中定義的,而且是protected型的,只有實現了這個接口,才可以在該類的實例上調用clone方法,否則會拋出CloneNotSupportException。説clone方法並沒有對對象是否屬於cloneable類型進行檢查這個觀點是不正確的。因為cloneable接口的出現跟接口的正常使用沒有任何關係,特別是它並不指定clone方法--------該方法從object類中繼承而來,該接口只是作為一個標記。這句話通俗的説就是以下3點:首先,clone方法是Object類的一個方法,所以任何類都會自動擁有這一個方法。其次,這並不説明該類就可以調用clone了,因為Javac或者java需要程序員顯示地指明該類可以調用clone,方法就是寫上這個字符串”implements Cloneable“。再次,這個字符串只是起一個指示作用,沒有其他功能,這是javac或者java的規定。