前言
日常写代码过程中我们需要对数据和对象等进行克隆,然而对引用类型必须要自己重写clone()
方法,对于复杂的对象并不那么好写,而且每个对象都需要重写一次。这里我不重写clone()
方法,而是使用输入输出流进行克隆。
通常在重写克隆方法时,除非是基础类型(byte/short/int/long/float/double/char/boolean),否则在不做处理的情况下,克隆出的对象其实都只是浅克隆。特别是对于多层嵌套的引用类型,必须对每一层都进行处理,否则最后都是指向同一块内存区域。但是下面的方法可以一劳永逸地解决这个问题。
代码
public void copyTest() throws ClassNotFoundException, IOException {
User u1 = new User(1, "yc");
User u2 = null;
// 使用ByteOutputStream和ObjectOutputStream将对象序列化
try (ByteOutputStream bos = new ByteOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos);) {
// 写入对象
oos.writeObject(u1);
oos.flush();
// 使用ByteArrayInputStream和ObjectInputStream反序列化
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.getBytes()));) {
// 读取对象
u2 = (User) ois.readObject();
}
}
// 修改原对象属性
u1.setId(2);
u1.setName("zy");
System.out.println("u1 = " + u1);
System.out.println("u2 = " + u2);
}
输出结果:
后记
该方法由hutool工具类库中的ObjectUtil.cloneByStream(T obj)
修改而来,主要是想学习其思想。核心思想都是将对象序列化后再反序列化,所以就要求被克隆必须实现Serializable
接口。建议直接使用ObjectUtil.cloneByStream(T obj)
。
关于深度克隆的推荐文章深入浅出Java中的clone克隆方法,写得太棒了!,顺便文中提到的String
类的不可变性Java 中的 String 真的是不可变的吗?