在JAVA中,我们想要实现对一个对象的克隆主要有两种方式
- 实现Cloneable接口并重写clone()方法;
- 实现Serializable接口,然后通过对象的序列化和反序列化操作实现真正的深度克隆。
我们首先写一个工具类,里面的代码即是我们通过序列化和反序列化实现克隆的核心代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class CloneUtil {
public static<T extends Serializable> T clone(T obj) throws Exception {
//序列化:将obj对象的内容进行流化,转化为字节序列写到内存的字节数组中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
//反序列化:读取内存中字节数组的内容,重新转换为java对象返回
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
}
}
再写一个"电脑"类和一个"Cpu"类进行实验
public class Computer implements Serializable{
private String computerName; //电脑名字
private Cpu cpu; //电脑的Cpu
public Computer() {
}
public Computer(String computerName, Cpu cpu) {
this.computerName = computerName;
this.cpu = cpu;
}
public String getComputerName() {
return computerName;
}
public void setComputerName(String computerName) {
this.computerName = computerName;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
@Override
public String toString() {
return "Computer{" +
"computerName='" + computerName + '\'' +
", cpu=" + cpu +
'}';
}
}
public class Cpu implements Serializable{
private String cpuName; //Cpu名字
private int price; //Cpu价格
public Cpu() {
}
public Cpu(String cpuName, int price) {
this.cpuName = cpuName;
this.price = price;
}
public String getCpuName() {
return cpuName;
}
public void setCpuName(String cpuName) {
this.cpuName = cpuName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Cpu{" +
"cpuName='" + cpuName + '\'' +
", price=" + price +
'}';
}
}
开始测试
public class CloneTest {
public static void main(String[] args) {
try {
Computer computer = new Computer("神州",new Cpu("酷睿I9",2300));
Computer cloneComputer = CloneUtil.clone(computer); //使用工具类clone得到
cloneComputer.getCpu().setCpuName("龙芯A3"); //修改克隆电脑的Cpu品牌
System.out.println(computer);
System.out.println(cloneComputer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结
由输出结果可知原computer的Cpu没有受到任何影响,符合深度克隆,同时,使用序列化和反序列化进行深度克隆不仅仅是为了克隆,更重要的是通过泛型限定可以检查出要克隆的对象是否已经支持序列化,这项检查由编译器完成,在编译时期就可以暴露出问题,这种处理方式要优于真正运行后再抛出错误。