通过 JDK 自带的字节流实现深克隆的方式,是先将要原型对象写入到内存中的字节流,然后再从这个字节流中读出刚刚存储的信息,来作为一个新的对象返回,那么这个新对象和原型对象就不存在任何地址上的共享,这样就实现了深克隆,代码如下
import java.io.*;
public class ThirdExample {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建对象
Address address = new Address(110, "北京");
People p1 = new People(1, "Java", address);
// 通过字节流实现克隆
People p2 = (People) StreamClone.clone(p1);
// 修改原型对象
p1.getAddress().setCity("西安");
// 输出 p1 和 p2 地址信息
System.out.println("p1:" + p1.getAddress().getCity() +
" p2:" + p2.getAddress().getCity());
}
/**
* 通过字节流实现克隆
*/
static class StreamClone {
public static <T extends Serializable> T clone(People obj) {
T cloneObj = null;
try {
// 写入字节流
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bo);
oos.writeObject(obj);
oos.close();
// 分配内存,写入原始对象,生成新对象
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());//获取上面的输出字节流
ObjectInputStream oi = new ObjectInputStream(bi);
// 返回生成的新对象
cloneObj = (T) oi.readObject();
oi.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
/**
* 用户类
*/
static class People implements Serializable {
private Integer id;
private String name;
private Address address;
// 忽略构造方法、set、get 方法
}
/**
* 地址类
*/
static class Address implements Serializable {
private Integer id;
private String city;
// 忽略构造方法、set、get 方法
}
}
以上程序的执行结果为:
p1:西安 p2:北京
此方式需要注意的是,由于是通过字节流序列化实现的深克隆,因此每个对象必须能被序列化,必须实现 Serializable 接口,标识自己可以被序列化,否则会抛出异常 (java.io.NotSerializableException)。
使用 Apache Commons Lang 来实现深克隆,实现代码如下:
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
/**
* 深克隆实现方式四:通过 apache.commons.lang 实现
*/
public class FourthExample {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建对象
Address address = new Address(110, "北京");
People p1 = new People(1, "Java", address);
// 调用 apache.commons.lang 克隆对象
People p2 = (People) SerializationUtils.clone(p1);
// 修改原型对象
p1.getAddress().setCity("西安");
// 输出 p1 和 p2 地址信息
System.out.println("p1:" + p1.getAddress().getCity() +
" p2:" + p2.getAddress().getCity());
}
/**
* 用户类
*/
static class People implements Serializable {
private Integer id;
private String name;
private Address address;
// 忽略构造方法、set、get 方法
}
/**
* 地址类
*/
static class Address implements Serializable {
private Integer id;
private String city;
// 忽略构造方法、set、get 方法
}
}