简介
- 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递的拷贝。
- 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象并复制其内容,做到了真正完全的拷贝。
浅拷贝实现
以下场景中有两个类,一个是Parent
,一个是Child
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class Parent implements Cloneable {
String parentName;
Child child;
public Parent(String parentName, Child child) {
this.parentName = parentName;
this.child = child;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Child {
String childName;
public Child(String childName) {
this.childName = childName;
}
}
要实现浅拷贝,只需要让Parent
实现Cloneable
接口,并覆盖Object
的clone()
方法即可。以下为测试代码:1
2
3
4
5
6
7
8
9
10
11
12
13public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Parent parent1 = new Parent("parent name", new Child("child name"));
Parent parent2 = (Parent) parent1.clone();
System.out.println(parent1 == parent2);
System.out.println(parent1.parentName);
System.out.println(parent2.parentName);
System.out.println("==================");
System.out.println(parent1.child == parent2.child);
System.out.println(parent1.child.childName);
System.out.println(parent2.child.childName);
}
}
控制台输出:1
2
3
4
5
6
7false
parent name
parent name
==================
true
child name
child name
可以看出,浅拷贝确实创建了一个新的Parent
对象,并且属性parentName
的值也一模一样,但是对于为引用类型的属性child
,实际上与之前引用的是同一个对象。
深拷贝实现
要实现深拷贝,常用的方案有以下两种:
- 序列化这个对象,再反序列化回来,就可以得到新的对象。
- 让属性也实现
Cloneable
。
属性实现Cloneable
1 | public class Parent implements Cloneable { |
和之前的浅拷贝不同之处在于这里Child
也实现了Cloneable
,并覆盖了clone()
方法,而Parent
的clone()
方法也有略微不同,在调用了clone()
方法后还调用了属性child
的clone()
方法重新设置属性,从而实现完完全全的拷贝。
此时控制台输出如下:1
2
3
4
5
6
7false
parent name
parent name
==================
false
child name
child name
注意到此时原始对象和拷贝对象的child
属性所引用的不再是同一个对象了。
序列化方式
1 | public class Parent implements Serializable { |
此时两个类都不需要再实现Cloneable
接口并覆盖clone()
方法了,但是它们都需要实现Serializable
接口,并且在Parent
的克隆方法中要实现序列化反序列化的逻辑,此时控制台输出如下:1
2
3
4
5
6
7false
parent name
parent name
==================
false
child name
child name