最近在做项目时,遇到一个java深拷贝的问题,常见有两种方式:
- 实现Cloneable接口,并且重写Object类中的clone()方法
- 实现Serializable接口序列化
详情请移步:Java对象-深拷贝(实现Serializable, Cloneable两种方式)
1. 实现Cloneable接口
public class Demo implements Cloneable {
private String name;
private String value;
private DemoInternal demoInternal;
/*省略getter和setter方法*/
@Override
public Demo clone() {
Demo demo = null;
try {
demo = (Demo) super.clone(); //浅复制
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
demo.demoInternal = demoInternal.clone(); //深度复制
return demo;
}
}
public class DemoInternal implements Cloneable {
private String internalName;
private String internalValue;
/*省略getter和setter方法*/
@Override
public DemoInternal clone() {
DemoInternal demoInternal = null;
try {
demoInternal = (DemoInternal) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return demoInternal;
}
}
2. 实现Serializable接口
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 通过字节流序列化实现深拷贝,需要深拷贝的对象必须实现Serializable接口
*
* @author Administrator
*/
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) {
T cloneObj = null;
try {
// 写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
// 分配内存,写入原始对象,生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
// 返回生成的新对象
cloneObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
3. 总结
上述的两种方式,都是通过一层又一层地深入,实现对象的深度复制。所以,如果您遇到类似于下面的问题时:
我已经实现了java.io.Serializable的接口了,为什么还提示我 NotSerializableException?
不要迷惑,一定是您忘记将某一个类实现Serializable接口,排错的方法是,使用try catch捕获异常,e.getMessage会打印出您忘记实现Serializable接口的类名,将该类实现Serializable接口即可。