java深度克隆和淺度克隆

java進行對象複製當然客以new 一個新的對象然後把原來對象的屬性值挨個複製到新的對象中去,可萬一屬性三四十個呢,不是很麻煩,於是便有了Java的Clone方法

Java對象要想具有Clone方法,首先要實現Cloneable接口,重寫Clone()方法,如

public class A  implements Cloneable{

	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	

}

Test方法

public void Test1() throws CloneNotSupportedException{
		A a=new A();
		a.setAge(22);
		a.setName("張三");
		A a1=(A) a.clone();
		System.out.println(a1==a);
		System.out.println(a1.getName()+":"+a1.getAge());		
	}

結果:

false
張三:22

 

可見Clone生成兩個不同的對象,而不僅僅是複製了地址的引用

但是有個問題是,Clone() 只支持全局變量類型爲8種基本類型和String類型的複製,對比如Date,ArrayList等其他引用類型只是複製了地址引用,這樣Clone出來的對象就失去了原有的意義了,即成爲淺度複製

如:

package cn.zw.learn.prototype;

public class A  implements Cloneable{

	private String name;
	private int age;
	private B b;	
	public B getB() {
		return b;
	}
	public void setB(B b) {
		this.b = b;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	

}

測試

 

	public void Test1() throws CloneNotSupportedException{
		A a=new A();
		a.setAge(22);
		a.setName("張三");
		B b=new B();
		b.setName("褲子");
		a.setB(b);
		A a1=(A) a.clone();
		System.out.println(a1==a);
		System.out.println(a.getB()==a1.getB());		
		System.out.println(a1.getName()+":"+a1.getAge());		
	}

}

結果

false
true
張三:22

這樣兩個對象就不完全獨立,失去了克隆的意義

爲了解決這一問題,我們在實現的clone()方法中,用序列化反序列化的方式得到一個新的Object並把它作爲返回值返回,做深度複製

改造如下

B類加上實現序列化接口

A類改造如下

package cn.zw.learn.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;



public class A  implements Cloneable,Serializable{

	private String name;
	private int age;
	private B b;	
	public B getB() {
		return b;
	}
	public void setB(B b) {
		this.b = b;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		ByteArrayOutputStream bos=null;
		ObjectOutputStream oos=null;
		ObjectInputStream ois=null;
		try {
			bos=new ByteArrayOutputStream();
			oos=new ObjectOutputStream(bos);
			oos.writeObject(this);			
	        ois=new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray()));
	        A a1= (A) ois.readObject();
			return a1;
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//下面的部分爲關閉流主要是上面的部分
			if (oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
			if (ois!=null) {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
			if (oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
		}
		
	
		return null;
	}
	

}

測試類大致不變

	public void Test1() throws CloneNotSupportedException{
		A a=new A();
		a.setAge(22);
		a.setName("張三");
		B b=new B();
		b.setName("褲子");
		a.setB(b);
		A a1=(A) a.clone();
		System.out.println(a1==a);
		System.out.println(a.getB()==a1.getB());		
		System.out.println(a1.getName()+":"+a1.getAge()+"," +a1.getB().getName());		
	}

}

 

結果如下

false
false
張三:22,褲子

完全沒有關係的兩個對象,且屬性全部複製,深度Clone

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章