深克隆與淺克隆
阿新 • • 發佈:2020-08-21
克隆是將一個物件複製成另一個完全相同的物件,但記憶體地址不同,修改原物件的值,克隆出的物件的值不會發生改變。
若某個類的物件需要進行克隆=>(深拷貝、淺拷貝)時,則這個類必須要實現 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; } 標準深拷貝和序列化深拷貝的區別:當一個物件底層包含有若干個物件時,標準的深克隆從最底層開始克隆,效率較低。 而序列化深拷貝直接將最外層的物件整體的序列化,再利用反序列化克隆出一個新的物件,效率較高。