1. 程式人生 > >Java基礎篇——深克隆與淺克隆

Java基礎篇——深克隆與淺克隆

基本定義

克隆,顧名思義,即是產生一個與原物件“完全”一樣的一個新物件。這裡的一樣,或許是表面的一樣,或許是真的一樣。這就牽扯到兩個新定義:淺克隆於深克隆。

淺克隆:新物件的基礎型別的變數值與原物件相同,而特殊物件,即非八大基本型別的物件與原物件指向同一記憶體空間,不管新老物件誰對這段空間進行操作都會影響到另一個,就像又要讓錢鍾書講三字經又要他講陶淵明,一人難敵兩角,肯定會引起問題,“假克隆”。

深克隆:新物件除了與老物件的八大基本型別的賦值一致以外,其類型別的物件在保證賦值一致的基礎上,指向的是一段新的記憶體空間,就像把同一斤大五花克隆兩份,一個給A廚師,一個給B廚師,你要東坡還是紅燒隨你便,最後出來的是完全不同的兩道菜,“真克隆”。

實現方式

1.將該類實現clonable介面;

2.並覆蓋Object的clone方法,設定為public關鍵字,原方法為protected;

3.在clone()中呼叫super.clone();

4.或者使用你的腦力自己實現一個克隆;

原理實現

1.深克隆

public class MecClone implements Serializable, Cloneable{
	private static final long serialVersionUID = 7511752675823078486L;
	
	public MecClone() {
	}
	
	private static void deleteResultObj(String path) {
		File file = new File(path);
		if(!file.isFile() || !file.exists()) {
			System.out.println("刪除" + path + "檔案失敗.....");
			return;
		}
		
		Boolean deleteSuccess = file.delete();
		if(deleteSuccess) {
			System.out.println("刪除" + path + "檔案成功!");
			return;
		}
	}
	
	// TODO 關於淺克隆的實現 未完成

	
	public Object deepClone(Object object) {
		Object result = null;
		try {
			ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("result.obj"));
			out.writeObject(object);
			out.close();
			
			ObjectInputStream in = new ObjectInputStream(new FileInputStream("result.obj"));
			result = in.readObject();
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		if(result == null) System.out.println("複製失敗!");
		deleteResultObj("result.obj");
		
		return result;
	}
}

原理:通過序列化方式,首先將需要複製的物件進行序列化,並將儲存著這個物件基本資訊的檔案儲存至磁碟,之後使用反序列化將物件讀取出來,並將檔案刪除。這樣,由於反序列化時JVM要根據序列號讀出類名、介面名、方法和屬性等資訊重新申請空間,指向的自然不是同一地址【此處可能有較大問題,歡迎大佬斧正】。Demo如下:

public class Demo {
	public static void main(String[] args) {
		MecClone mecClone = new MecClone();
		UserModel userOne = new UserModel().setName("pikachew").setPassword("pikapika").setAge("99");
		UserModel userTwo = (UserModel) mecClone.deepClone(userOne);
		userTwo.setName("Raychew").setPassword("rayray").setAge("88");
		
		System.out.println(userTwo);
		System.out.println(userOne);
	}
}
刪除result.obj檔案成功!
Raychew rayray 的年齡88
pikachew pikapika 的年齡99

2.淺克隆

可以簡單的通過實現介面、覆蓋clone()方法實現,此處不予演示。