深拷贝 & 浅拷贝

Posted by zhidaliao on October 23, 2015

在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

浅拷贝

public class CloneSimpleTest {
	public static void main(String[] args) {
		
		People people = new People("tom", new Food("100k"));
		People clonePeople = (People) people.clone();
		
		System.out.println("--初始数据--");
		System.out.println(people.name);
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.name);
		System.out.println(clonePeople.food.calorie);
		
		System.out.println("--修改对象实例--");
		people.food.calorie = "200k";
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.food.calorie);
	}
}

class People implements Cloneable {
	
	String name;
	Food food;

	People() {

	}

	People(String name, Food food) {
		this.name = name;
		this.food = food;

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Food getFood() {
		return food;
	}

	public void setFood(Food food) {
		this.food = food;
	}

	@Override
	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

}

class Food {
	
	String calorie;

	Food(String calorie) {
		this.calorie = calorie;
	}

	public String getCalorie() {
		return calorie;
	}

	public void setCalorie(String calorie) {
		this.calorie = calorie;
	}

}

output:

--初始数据--
tom
100k
tom
100k
--修改对象实例--
200k
200k

深拷贝

重写 clone 方法
public class CloneDeepTest {
	public static void main(String[] args) {

		PeopleDeep people = new PeopleDeep("tom", new FoodDeep("100k"));
		PeopleDeep clonePeople = (PeopleDeep) people.clone();

		System.out.println("--初始数据--");
		System.out.println(people.name);
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.name);
		System.out.println(clonePeople.food.calorie);

		System.out.println("--修改对象实例--");
		people.food.calorie = "200k";
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.food.calorie);
	}
}

class PeopleDeep implements Cloneable {

	String name;
	FoodDeep food;

	PeopleDeep() {

	}

	PeopleDeep(String name, FoodDeep food) {
		this.name = name;
		this.food = food;

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public FoodDeep getFood() {
		return food;
	}

	public void setFood(FoodDeep food) {
		this.food = food;
	}

	@Override
	public Object clone() {
		try {
			PeopleDeep pd = (PeopleDeep) super.clone();
			pd.food = (FoodDeep) this.food.clone();
			return pd;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

}

class FoodDeep implements Cloneable {

	String calorie;

	FoodDeep(String calorie) {
		this.calorie = calorie;
	}

	public String getCalorie() {
		return calorie;
	}

	public void setCalorie(String calorie) {
		this.calorie = calorie;
	}

	@Override
	public Object clone() {
		try {
			return super.clone();
		} catch (Exception e) {
		}
		return null;
	}

}

output:

--初始数据--
tom
100k
tom
100k
--修改对象实例--
200k
100k

序列化
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class CloneSeriaTest {
	public static void main(String[] args) {

		PeopleSeria people = new PeopleSeria("tom", new FoodSeria("100k"));
		PeopleSeria clonePeople = CloneSeriaTest.seriaClone(people);

		System.out.println("--初始数据--");
		System.out.println(people.name);
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.name);
		System.out.println(clonePeople.food.calorie);

		System.out.println("--修改对象实例--");
		people.food.calorie = "200k";
		System.out.println(people.food.calorie);
		System.out.println(clonePeople.food.calorie);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T seriaClone(Object obj) {

		T cloneObj = null;
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

		try (ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);) {
			oos.writeObject(obj);
		} catch (Exception e) {
			e.printStackTrace();
		}

		try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
				ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
		) {
			cloneObj = (T) ois.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return cloneObj;
	}
}

class PeopleSeria implements Serializable {

	private static final long serialVersionUID = -9119506911414650261L;

	String name;
	FoodSeria food;

	PeopleSeria() {

	}

	PeopleSeria(String name, FoodSeria food) {
		this.name = name;
		this.food = food;

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public FoodSeria getFood() {
		return food;
	}

	public void setFood(FoodSeria food) {
		this.food = food;
	}
}

class FoodSeria implements Serializable {

	private static final long serialVersionUID = -1787796699785618116L;
	String calorie;

	FoodSeria(String calorie) {
		this.calorie = calorie;
	}

	public String getCalorie() {
		return calorie;
	}

	public void setCalorie(String calorie) {
		this.calorie = calorie;
	}
}

output:

--初始数据--
tom
100k
tom
100k
--修改对象实例--
200k
100k

参考网站