Java中深拷贝与浅拷贝

深拷贝与浅拷贝

在Java中,有两种方式可以创建对象,第一种是使用new操作符创建对象,第二种是使用clone方法复制一个对象。
下面这段代码创建了magazine2对象并将magazine2的引用指向了magazine1的对象

1
2
3
4
Magazine magazine1 = new Magazine("Times",100);
Magazine magazine2 = magazine1;
System.out.println(magazine1.hashCode());
System.out.println(magazine2.hashCode());

输出结果

1
2
2027961269
2027961269

打印hashCode,发现它们两个对象的hashCode值一样,那么此时它们的地址当然是一样的,其实magazine1和magazine2指向的同一个对象Magazine(“Times”, 100),只不过它们是指向相同对象的两个不同的引用而已。
如下图所示
ShowImage

使用clone()方法复制对象

1
2
3
4
Magazine magazine1 = new Magazine("Times",100);
Magazine magazine2 = (Magazine) magazine1.clone();
System.out.println(magazine1.hashCode());
System.out.println(magazine2.hashCode());

输出结果

1
2
2027961269
1586270964

这次使用clone()方法复制一个对象,打印hashCode不同,这次指向的不是同一个对象了
如下图所示
ShowImage

但是这次拷贝发现,magazine1对象中的String属性name和magazine2对象中的String属性name内容不一样,为什么呢,因为直接实现Cloneable接口重写clone方法这种方式是浅拷贝。

浅拷贝的定义是

使用一个已知实例对新创建实例的成员变量逐个赋值

与浅拷贝对应的是深拷贝

当一个类的拷贝方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。

通俗点来说,就是浅拷贝方式只能复制原来实例对象中的基本类型,像int,double这种,不能复制String,List,Map这样的对象类型或者自定义的对象类型。而深拷贝不仅会复制基本类型的值,而且还会复制对象类型的引用比如Book类

1
2
3
4
public class Book {
private String name;
private int page;
}

Book的对象如果使用浅拷贝,那么name值不能复制过去,但是用深拷贝name值也可以复制过去。

但是问题又来了,如果修改下Book类

1
2
3
4
5
public class Book {
private String name;
private int page;
private Bookmark bookmark;
}

增加一个Bookmark的成员

1
2
3
4
public class Bookmark {
private String mark;
private int markPage;
}

现在对Book对象进行复制,bookmark中的String对象mark又不能复制了。这是因为在深拷贝之中只能复制一级引用,好比集装箱一样,浅拷贝不能去复制集装箱里面装的小集装箱,深拷贝可以复制集装箱中的小集装箱,但是如果小集装箱里面还有若干个集装箱,那么此时就无能为力了,想要拷贝就必须再往下一层继续实现深拷贝的方法。所以深拷贝在多级引用上的对象中实现是比较复杂的,要想彻底的深拷贝对象,需要每一级都去实现深拷贝方法。

参考代码

------ 本文结束 ------

版权声明


BillyYccc's blog by Billy Yuan is licensed under a Creative Commons BY-NC-SA 4.0 International License.
本文原创于BillyYccc's Blog,转载请注明原作者及出处!