浅拷贝和深拷贝
在Java语言中如果我们想要拷贝一个对象,有两种拷贝方式深拷贝和浅拷贝
浅拷贝在拷贝的时候只复制了对象的引用,实际使用还是堆中同一份对象.改变A中的属性后,B也会改变
深拷贝会在堆中创建一个新对象并和之前对象属性相同,因此改变源对象A后,B也不会改变
浅拷贝的实现方法
通过将要拷贝的类实现Clonable接口,重写clone方法
方法内部调用super.clone()方法.
package 笔记代码.深拷贝;
import java.util.ArrayList;
public class PCB implements Cloneable{
int a;
Integer b;
ArrayList<Integer> list = new ArrayList<>();
public PCB(){
for (int i = 0; i < 100; i++) {
list.add(i);
}
}
public ArrayList<Integer> getList() {
return list;
}
public void setList(ArrayList<Integer> list) {
this.list = list;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public Integer getB() {
return b;
}
public void setB(Integer b) {
this.b = b;
}
@Override
public PCB clone() {
try {
PCB clone = (PCB) super.clone();
// TODO: 复制此处的可变状态,这样此克隆就不能更改初始克隆的内部
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
从调试结果可以看出pcb与clone不是一个对象,但是其内部引用类型的成员变量的地址都没有发生变化.如同上面结构
实现方式
实现Clonable接口,重写clone方法
上述深拷贝都需要自己一条条属性进行实现,如果后续添加了属性那么将会非常麻烦
因此我们可以使用一些拷贝工具
序列化方式
public PCB cloneSerializable() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (PCB) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
也可以使用fastjson Gson等第三方工具进行序列化