1. 程式人生 > 實用技巧 >深克隆與淺克隆

深克隆與淺克隆

克隆是將一個物件複製成另一個完全相同的物件,但記憶體地址不同,修改原物件的值,克隆出的物件的值不會發生改變。
若某個類的物件需要進行克隆=>(深拷貝、淺拷貝)時,則這個類必須要實現 Cloneable 介面【若果沒有實現這個介面,則會丟擲
CloneNotSupportedException(克隆不支援異常)】,並且需要在這個類中重寫 Object 類中的 clone() 方法。

淺拷貝=>僅僅複製物件本身,基本資料型別進行復制後修改某一物件的屬性,不會讓其他物件也被修改,而當類中包含其他類的物件

時,僅複製其他類的物件的記憶體地址,修改一處後會使其他物件都被修改。

例: protected Weapon clone() throws CloneNotSupportedException {
	
	return (Weapon)super.clone();
}

深拷貝(標準)=>利用淺拷貝的方式將其他類的物件向下一層進行復制,然後通過set方法設定給上一層,最終將底層的所有物件全部複製,

修改任何值,都不會對其他屬性造成影響。
例:protected Robot clone() throws CloneNotSupportedException {
Robot robot = (Robot)super.clone();
Weapon weapon = robot.getWeapon().clone();
robot.setWeapon(weapon);;
return robot;
}
protected Weapon clone() throws CloneNotSupportedException {

	return (Weapon)super.clone();
}

深拷貝(序列化)=>功能和標準的深拷貝相同,但序列化深拷貝是直接將物件序列化成位元組流,再將位元組流反序列化成為新的物件。

使用這種方法不用實現 Cloneable 介面,但是當前類和其使用到的類都需要實現 Serializable 介面,然後再該類中自定義一個克隆方法(deepClone)。
首先利用 byteArrayOutputStream(位元組陣列輸出流) 和 ObjectOutputStream (物件輸出流)將物件序列化成位元組流,然後利用
byteArraryInputStream(位元組陣列輸入流)和 ObjectInputStream(物件輸入流)將位元組流反序列化成為新的物件

例:protected Robot deepClone() throws Exception {
	將當前物件“Robot物件”轉化為字元流(序列化)
	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	ObjectOutputStream oos = new ObjectOutputStream(bos);
	oos.writeObject(this);
	
	將位元組流轉換成“新的Robot物件”(反序列化)
	ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
	ObjectInputStream ois = new ObjectInputStream(bis);
	Robot robot = (Robot)ois.readObject();
	
	return robot;
}
標準深拷貝和序列化深拷貝的區別:當一個物件底層包含有若干個物件時,標準的深克隆從最底層開始克隆,效率較低。
			     而序列化深拷貝直接將最外層的物件整體的序列化,再利用反序列化克隆出一個新的物件,效率較高。