关于Java的深、浅拷贝的误用

Java都继承自Object,自带clone的native方法,但其实只能实现浅拷贝通过implements Cloneable(虽然是个空方法),通过手工实现clone,才能实现深度拷贝。

容易发生误用的情况, 类变量是个类情况下,以为只要类变量实现了clone方法,就可以实现类的深拷贝,其实,这个时候也要 在clone方法中对类变量进行clone,否则还是浅拷贝。废话少说,代码如下:

1、没有实现clone的情况
public class Dog {
	public int legCounts;
	
	public Dog(int legCounts) {
		this.legCounts = legCounts;
	}
	
	public void changeLegCounts() {
		this.legCounts *= 2;
	}
	
	public String toString() {
		return Integer.toString(legCounts);
	}
}

public class GouClone implements Cloneable {
	public int legCounts;
	Dog dog = new Dog(4);
	
	protected GouClone clone() throws CloneNotSupportedException {
		return (GouClone)super.clone();
	}
}


public class Client {

	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		GouClone gouClone = new GouClone();
		gouClone.legCounts = 3;
		System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
		System.out.println("原普通狗的数量:" + gouClone.dog);
		
		GouClone gouClone1 = (GouClone)gouClone.clone();
		gouClone1.legCounts = 2;
		
		Dog dog = gouClone1.dog;
		dog.changeLegCounts();
		System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
		System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
		System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
	}

}


结果是:
原拷贝狗腿的数量:3
原普通狗腿的数量:4
拷贝后,原来普通狗的数量:8
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8


2、只实现了clone方法,类变量没有clone
public class Dog implements Cloneable {
	public int legCounts;
	
	public Dog(int legCounts) {
		this.legCounts = legCounts;
	}
	
	public void changeLegCounts() {
		this.legCounts *= 2;
	}
	
	public Dog clone() throws CloneNotSupportedException {
		return (Dog)super.clone();
	}
	
	public String toString() {
		return Integer.toString(this.legCounts);
	}
}

public class GouClone implements Cloneable {
	public int legCounts;
	Dog dog = new Dog(4);
	
	protected GouClone clone() throws CloneNotSupportedException {
		GouClone clone = (GouClone)super.clone();
		return clone;
	}
}

public class Client {

	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		GouClone gouClone = new GouClone();
		gouClone.legCounts = 3;
		System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
		System.out.println("原普通狗的数量:" + gouClone.dog);
		
		GouClone gouClone1 = (GouClone)gouClone.clone();
		gouClone1.legCounts = 2;
		
		Dog dog = gouClone1.dog;
		dog.changeLegCounts();
		System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
		System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
		System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
	}

}

结果是:
原拷贝狗腿的数量:3
原普通狗腿的数量:4
拷贝后,原来普通狗的数量:8
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8


3、类变量也在clone中体现,真正实现深拷贝
public class Dog implements Cloneable {
	public int legCounts;
	
	public Dog(int legCounts) {
		this.legCounts = legCounts;
	}
	
	public void changeLegCounts() {
		this.legCounts *= 2;
	}
	
	public Dog clone() throws CloneNotSupportedException {
		return (Dog)super.clone();
	}
	
	public String toString() {
		return Integer.toString(this.legCounts);
	}
}

public class GouClone implements Cloneable {
	public int legCounts;
	Dog dog = new Dog(4);
	
	protected GouClone clone() throws CloneNotSupportedException {
		GouClone clone = (GouClone)super.clone();
		clone.dog = clone.dog.clone();
		return clone;
	}
}

public class Client {

	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		GouClone gouClone = new GouClone();
		gouClone.legCounts = 3;
		System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
		System.out.println("原普通狗的数量:" + gouClone.dog);
		
		GouClone gouClone1 = (GouClone)gouClone.clone();
		gouClone1.legCounts = 2;
		
		Dog dog = gouClone1.dog;
		dog.changeLegCounts();
		System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
		System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
		System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
	}

}

结果是:

原拷贝狗腿的数量:3
原普通狗的数量:4
拷贝后,原来普通狗的数量:4
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8


当然,除了类变量clone在clone()方法中体现,也可以通过引用类实现Serializable接口,并在clone()方法中将对象从流中取出,也是一个办法。

猜你喜欢

转载自xwhuang.iteye.com/blog/2323954