# 简介
- 浅拷贝:对基本数据类型进行值的传递,对引用数据类型进行引用传递的拷贝;
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容;
# 浅拷贝
首先创建一个 Parent 类和 Child 类,实现浅拷贝只需要让 Parent 类继承 Cloneable 接口,并且重写clone() 方法。 ```java public class Parent implements Cloneable { String parentName; Child child;
public Parent(String parentName, Child child) {
this.parentName = parentName;this.child = child;
}
@Override protected Object clone() throws CloneNotSupportedException {
return super.clone();
} }
public class Child { String childName;
public Child(String childName) {this.childName = childName;}
}
```javapublic 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: " + parent1.hashCode());System.out.println("parent2: " + parent2.hashCode());System.out.println("==============");System.out.println(parent1.child == parent2.child);System.out.println("child1: " + parent1.child.hashCode());System.out.println("child2: " + parent2.child.hashCode());System.out.println(parent1.child.childName);System.out.println(parent2.child.childName);}}
falseparent1: 1456208737parent2: 25126016parent nameparent name==============truechild1: 762218386child2: 762218386child namechild name
通过 hashCode() 和 == 我们可以发现,浅拷贝确实创建了一个新的对象。但是对于引用类型的属性child 而言,从 hashCode() 可以发现浅拷贝过后仍然引用了相同的 Child 对象,即浅拷贝只传递了属性为引用类型的引用。
# 深拷贝
常用实现深拷贝的方案有两种:
- 序列化这个对象,再反序列化回来,就可以得到这个新的对象。
继续利用 clone() 方法,让属性实现 Cloneable 接口。
| 属性实现 Cloneable 接口
和之前的浅拷贝不同之处在于这里 Child 也实现了 Cloneable,并重写了 clone() 方法,而 Parent 的clone() 方法也有略微不同,在调用了 clone() 方法后还调用了属性 child 的 clone() 方法重新设置属性,实现完全的拷贝。 ```java public class Parent implements Cloneable { String parentName; Child child;
public Parent(String parentName, Child child) {
this.parentName = parentName;this.child = child;
}
@Override protected Object clone() throws CloneNotSupportedException {
Parent parentclone = (Parent) super.clone();parentclone.child = (Child) this.child.clone();return parentclone;
} }
public class Child implements Cloneable { String childName;
public Child(String childName) {this.childName = childName;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
```javafalseparent1: 1456208737parent2: 25126016parent nameparent name==============falsechild1: 762218386child2: 672320506child namechild name
通过 hashCode() 可以发现,原始对象和拷贝对象的属性 child 已经是两个不同的对象。
| 序列化
两个类都不需要再实现 Cloneable 接口并重写 clone() 方法了,但是它们都需要实现 Serializable 接口,并且在 Parent 的克隆方法中要实现序列化反序列化的逻辑。
public class Parent implements Serializable {String parentName;Child child;public Parent(String parentName, Child child) {this.parentName = parentName;this.child = child;}public Object deepClone() throws Exception {// 将对象写到流里OutputStream bo = new ByteArrayOutputStream();ObjectOutputStream oo = new ObjectOutputStream(bo);oo.writeObject(this);// 从流里读对象出来// toByteArray()创建一个新分配的字节数组。数组的大小和当前输出流的大小,内容是当前输出流的拷贝。InputStream bi = new ByteArrayInputStream(((ByteArrayOutputStream) bo).toByteArray());ObjectInputStream oi = new ObjectInputStream(bi);return oi.readObject();}}public class Child implements Serializable {String childName;public Child(String childName) {this.childName = childName;}}
falseparent nameparent name==================falsechild namechild name
