JAVA SE之Cloneable 深拷贝和浅拷贝的区别

时间:2022-03-17 19:55:55

对照下面的例子很容易看出:
当一个对象赋值给另一个对象变量时,是相同的引用,公用这个对象实例;
浅拷贝,需要实现Cloneable这个标记接口,然后自行实现clone方法,clone方法的默认就是浅拷贝;注意:当对象中成员变量都是基本类型或者不可变量如String的时候,浅拷贝是安全的。
但是当变量中存在子对象变量的引用时,就需要深拷贝了,因为浅拷贝并不会对子对象进行clone,这样就造成子对象变为共享域,对象和对象副本都会造成它的状态等改变。因此,深拷贝就类似于递归的把对象本身及对象中包含的对象都进行clone。

package learning.copy;

/**
*@className SuperficialCopy
*@description :浅拷贝,当对象本身不含有子对象引用的时候,浅拷贝是安全的
* clone方法的默认就是浅拷贝,深拷贝需要自己去实现。
*@author Wanggd @date 2017年5月27日上午11:20:23
*/

public class SuperficialCopy implements Cloneable{

String name;
int age;

SuperficialCopy(String name,int age){
this.age = age;
this.name = name;
}

@Override
public Object clone() throws CloneNotSupportedException{

Object o = super.clone();
return o;
}

public static void main(String[] args) throws CloneNotSupportedException {
SuperficialCopy obj1 = new SuperficialCopy("Kevin",20);

SuperficialCopy copyObj = (SuperficialCopy) obj1.clone();
copyObj.age = 80;
System.out.println("object1's age = " + obj1.age );
//结果:object1's age = 20

SuperficialCopy obj2 = obj1;
obj2.age = 90;
System.out.println("changed by obj2 object1's age = " + obj1.age );
//changed by obj2 object1's age = 90
}

}
package learning.copy;

/**
*@className SuperficialCopyHasObj
*@description :浅拷贝,当浅拷贝发生在对象含有子对象引用的时候,浅拷贝就不再是安全的。
*@author Wanggd @date 2017年5月27日上午11:21:48
*
*/

public class SuperficialCopyHasObj implements Cloneable{

private String name;
private int age;
private Inner inner;

SuperficialCopyHasObj(String name,int age,Inner inner){
this.age = age;
this.name = name;
this.inner = inner;
}

@Override
public Object clone() throws CloneNotSupportedException{

Object o = super.clone();
return o;
}

public static void main(String[] args) throws CloneNotSupportedException {
SuperficialCopyHasObj obj1 = new SuperficialCopyHasObj("Kevin",20,new Inner("who",66));
System.out.println("Before object1's inner name = " + obj1.inner.getInnerName() );
//结果:Before object1's inner name = who

SuperficialCopyHasObj copyObj = (SuperficialCopyHasObj) obj1.clone();
copyObj.age = 80;
System.out.println("object1's age = " + obj1.age );
//结果:object1's age = 20

copyObj.inner.setInnerName("what");
System.out.println("object1's inner name = " + obj1.inner.getInnerName() );
//object1's inner name = what

}

}
package learning.copy;

/**
*@className DeepCopy
*@description :深度拷贝,对象本身及包含的对象引用也要clone
*@author Wanggd @date 2017年5月27日上午11:19:23
*/

public class DeepCopy implements Cloneable{
private String name;
private int age;
private Inner inner;

DeepCopy(String name, int age, Inner inner){
this.name = name;
this.age = age;
this.inner = inner;
}

public Object clone(){
DeepCopy o = null;
try {
o = (DeepCopy)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
o.inner = (Inner)inner.clone();
return o;
}

public static void main(String[] args) {
Inner inner = new Inner("I'm inner",10);
DeepCopy obj1 = new DeepCopy("I'm kevin", 20, inner);

DeepCopy copyObj = (DeepCopy) obj1.clone();
copyObj.setAge(88);
copyObj.inner.setInnerAge(90);
copyObj.inner.setInnerName("changes");

System.out.println("obj1's age=" + obj1.age + ",obj1's inner name=" + obj1.inner.getInnerName());
//结果:obj1's age=20,obj1's inner name=I'm inner
}

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;
}

public Inner getInner() {
return inner;
}

public void setInner(Inner inner) {
this.inner = inner;
}


}

class Inner implements Cloneable{

private String innerName;
private int innerAge;

Inner(String innerName, int innerAge){
this.innerAge = innerAge;
this.innerName = innerName;
}

public String getInnerName() {
return innerName;
}

public void setInnerName(String innerName) {
this.innerName = innerName;
}

public int getInnerAge() {
return innerAge;
}

public void setInnerAge(int innerAge) {
this.innerAge = innerAge;
}

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

}