大家好,我是孤焰。今天要谈一谈在面试过程中可能被面试官提到的一个问题——深拷贝和浅拷贝的区别?
由于我也是刚刚学习编程的小白,所以此篇博文将参考了多篇博文,最后总结而成。
最近由于多门考试临近,所以博文更新速度可能会慢一些,希望大家谅解。
在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 = 号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。
1.浅拷贝
浅拷贝:浅拷贝时被复制对象中的成员变量若为引用数据类型,那么只将此成员对象的引用复制,而不重新实例新的成员对象。换言之,被复制的对象的所有的变量都与原对象有相同的值,而所有的引用对象仍然指向原来的对象。
代码举例如下:
//测试类
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
//原始对象
ShallowCopy shallowCopy = new ShallowCopy();
shallowCopy.setBaseType(1);
shallowCopy.setObjectClass("我是孤焰");
//复制对象
ShallowCopy shallowCopy2 = (ShallowCopy) shallowCopy.clone();
shallowCopy.setBaseType(2);
shallowCopy.setObjectClass("我是修改后的孤焰");
System.out.println("原始对象的基础类型值为:" + shallowCopy.getBaseType());
System.out.println("原始对象的引用类型的地址为:" + shallowCopy.getObjectClass());
System.out.println();
System.out.println("复制对象的基础类型值为:" + shallowCopy2.getBaseType());
System.out.println("复制对象的引用类型的地址为:" + shallowCopy2.getObjectClass());
}
}
class ObjectClass {
private String content;
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "ObjectClass{" +
"content='" + content + '\'' +
'}';
}
}
class ShallowCopy implements Cloneable {
private int baseType;
private ObjectClass objectClass;
public ShallowCopy() {
objectClass = new ObjectClass();
}
public int getBaseType() {
return baseType;
}
public void setBaseType(int baseType) {
this.baseType = baseType;
}
public ObjectClass getObjectClass() {
return objectClass;
}
public void setObjectClass(String value) {
this.objectClass.setContent(value);
}
//浅拷贝的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
程序运行结果为:
可以发现在对shallowCopy
对象浅拷贝之后修改了shallowCopy
对象中的引用类型对象的值,然后复制对象shallowCopy2
中的引用类型对象的值也改变了,那么就证明了浅拷贝仅仅是将对象中引用类型变量的地址复制,而不是重新实例化一个新的引用类型对象。
2.深拷贝
深拷贝:深拷贝时会将被复制对象中的引用数据类型的成员变量的副本以及基本数据类型的变量的值赋值给新的对象。
对上个例子进行简单改动后,代码如下:
//测试类
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
//原始对象
ShallowCopy shallowCopy = new ShallowCopy();
shallowCopy.setBaseType(1);
shallowCopy.setObjectClass("我是孤焰");
//复制对象
ShallowCopy shallowCopy2 = (ShallowCopy) shallowCopy.clone();
shallowCopy.setBaseType(2);
shallowCopy.setObjectClass("我是修改后的孤焰");
System.out.println("原始对象的基础类型值为:" + shallowCopy.getBaseType());
System.out.println("原始对象的引用类型的值为:" + shallowCopy.getObjectClass());
System.out.println();
System.out.println("复制对象的基础类型值为:" + shallowCopy2.getBaseType());
System.out.println("复制对象的引用类型的值为:" + shallowCopy2.getObjectClass());
}
}
class ObjectClass implements Cloneable {
private String content;
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "ObjectClass{" +
"content='" + content + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class ShallowCopy implements Cloneable {
private int baseType;
private ObjectClass objectClass;
public ShallowCopy() {
objectClass = new ObjectClass();
}
public int getBaseType() {
return baseType;
}
public void setBaseType(int baseType) {
this.baseType = baseType;
}
public ObjectClass getObjectClass() {
return objectClass;
}
public void setObjectClass(String value) {
this.objectClass.setContent(value);
}
//深拷贝的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
ShallowCopy shallowCopy = (ShallowCopy) super.clone();
shallowCopy.objectClass = (ObjectClass) this.objectClass.clone();
return shallowCopy;
}
}
程序运行结果为:
将clone()
方法更改为深拷贝之后,可以发现现在shallowCopy
对象中引用类型的值被修改并没有影响到shallowCopy2
对象中引用类型的值。
3.总结
通过上面举例,相信大家也可以分清深拷贝和浅拷贝的区别了,下面用两幅图来总结他们的区别。
浅拷贝是拷贝基本类型变量的值和引用类型变量的地址值。
深拷贝会拷贝基本类型变量的值和引用类型变量的实例化。
4.最后
都看到最后了,求求大家点个赞再走吧!你的支持是博主创作的最大动力。