浅拷贝与深拷贝是什么
浅拷贝和深拷贝本质都是对一个已有引用对象进行拷贝操作,但二者存在一定的区别。
在 Java 中,数据类型分为 基本数据类型(元类型)和 引用数据类型。而一般使用 『 = 』号做赋值操作的时候,对于基本数据类型,实际上是拷贝的它的值,但是对于引用数据类型而言,其实将原对象的引用传递过去,它们实际是指向同一个对象。
而浅拷贝和深拷贝的区别就在于:在拷贝某个对象的时候,如果只对基本数据类型的成员变量进行了值的拷贝,而对引用数据类型的成员变量只是进行了引用的传递,而没有为其创建一个新的对象,是浅拷贝;反之,在对引用数据类型的成员变量进行拷贝的时候,为其创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。
所以浅拷贝和深拷贝的本质是 对某个对象的引用数据类型的成员变量的不同操作而已。
浅拷贝
对基本数据类型进行值传递,对引用数据类型进行引用传递的拷贝。
深拷贝
对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容。
Java中的clone方法
在 Java 中,所有的类都继承自 Object 。在 Object 中有一个 clone() 方法,浅拷贝和深拷贝 需要实现 clone() 方法,来完成操作。
通过注释我们知道所有调用 clone() 方法的对象,都必须实现 Cloneable 接口,否则将抛 CloneNotSupportedException 异常。
浅拷贝示例
private class BoyObject implements Cloneable{
public String name;
public int age;
public GirlFriend girlFriend;
@Override
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e);
}
return null;
}
}
private class GirlFriend implements Cloneable{
public String name;
public int age;
@Override
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e);
}
return null;
}
}
public void cloneTest() {
BoyObject boyObject = new BoyObject();
boyObject.girlFriend = new GirlFriend();
boyObject.name = "xiaoqiang";
boyObject.age = 18;
boyObject.girlFriend.name = "xiaoli";
boyObject.girlFriend.age = 18;
BoyObject cloneObject = (BoyObject)boyObject.clone();
System.out.println("boyObject hashcode=" + boyObject.hashCode());
System.out.println("boyObject name=" + boyObject.name);
System.out.println("boyObject age=" + boyObject.age);
System.out.println("boyObject girlFriend hashcode=" + boyObject.girlFriend.hashCode());
System.out.println("cloneObject hashcode=" + cloneObject.hashCode());
System.out.println("cloneObject name=" + cloneObject.name);
System.out.println("cloneObject age=" + cloneObject.age);
System.out.println("cloneObject girlFriend hashcode=" + cloneObject.girlFriend.hashCode());
}
运行测试方法,输出如下:
boyObject hashcode=935044096
boyObject name=xiaoqiang
boyObject age=18
boyObject girlFriend hashcode=396180261
cloneObject hashcode=625576447
cloneObject name=xiaoqiang
cloneObject age=18
cloneObject girlFriend hashcode=396180261
由上可知,boyObject 与 cloneObject 的hashcode不同,说明 由boyObject.clone() 得到了一个新的 BoyObject 对象。但这是一次浅拷贝,因为 boyObject.girlFriend .hashcode 与 cloneObject.girlFriend.hashcode 一致,说明在boyObject 拷贝时girlFriend 只是进行了应用传递,而没有创建一个新的 GirlFriend 对象。boyObject 与 cloneObject 的 girlFriend 属性指向同一个对象。
深拷贝实例
深拷贝只做以下改动,其他保持不变:
private class BoyObject implements Cloneable{
public String name;
public int age;
public GirlFriend girlFriend;
@Override
public Object clone(){
try {
BoyObject cloneObject = (BoyObject)super.clone();
cloneObject.girlFriend = (GirlFriend)this.girlFriend.clone();
return cloneObject;
} catch (CloneNotSupportedException e) {
System.out.println(e);
}
return null;
}
}
重新运行后输出如下:
boyObject hashcode=935044096
boyObject name=xiaoqiang
boyObject age=18
boyObject girlFriend hashcode=396180261
cloneObject hashcode=625576447
cloneObject name=xiaoqiang
cloneObject age=18
cloneObject girlFriend hashcode=1560911714
由上可知,boyObject.girlFriend .hashcode 与 cloneObject.girlFriend.hashcode 不一致,说明boyObject.clone()方法在拷贝时创建了一个新的 GirlFriend 对象赋值给了cloneObject的 girlFriend属性,是深拷贝。