高质量编码--使用序列化实现对象的拷贝
#回顾
回顾下对象拷贝的知识,为什么要拷贝对象呢,因为new对象往往是消耗资源的,使用对象拷贝的方式可以节省创建对象时的资源消耗,尤其对于大对象而言
我们可以看下简单实现,下面这个类实现了Cloneable接口
public class Person implements Cloneable{
private String name;
private Person parent;
Person(String name){
this.name = name;
}
Person(String name,Person parent){
this.name = name;
this.parent = parent;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// get,set方法省略...
}
类有了,下面这个方法会输出什么呢?
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person father = new Person("老爹");
Person xiaoming = new Person("小明", father);
Person xiaogang = xiaoming.clone();
xiaogang.name = "小刚";
xiaoming.parent.name = "干爹";
System.out.printf("%s的父亲-%s\n",xiaoming.name,xiaoming.parent.name);
System.out.printf("%s的父亲-%s\n",xiaogang.name,xiaogang.parent.name);
}
Look
我们现在假设个场景,小明和小刚是兄弟,他们俩的老爹欠了隔壁王大爷5块钱,木钱还咋办,老王说你让一个儿子认我做干爹,这事算结了,老爹没办法啊,只好同意了,于是小明认了老王做干爹,小刚看见了也去认老王当干爹去了,得,两个儿子全没了,老爹要气死
这里就涉及到了浅拷贝的知识
#浅拷贝
调用clone方法只会复制对象的基本类型和String,而对象则是复制引用,即小明和小刚的引用都是指向同一个父亲。
有没有办法给小刚复制一个父亲,这样小明修改父亲属性就不会影响到小刚了。
#重写clone方法
其实是有办法的,代码如下,给小刚重新new一个父亲就行。
protected Person clone() throws CloneNotSupportedException {
Person person = super.clone();
person.setPerson(new Person(person.getName));
return person;
}
#序列化
我们考虑这样一个问题,每次对象复制都要重写clone对象是不是很费事
因此我们想到了其他方法,我们可以通过序列化的方式来处理,在内存中通过字节流的拷贝来实现。
也就是把小明写到一个字节流中,再从字节流中读出来,这样就可以重建一个新对象了,这个对象跟小明不存在引用共享的问题,相当于深拷贝一个对象。
代码如下
class CloneUtils{
// 拷贝一个对象
public static <T extends Serializable> T clone(T obj){
// 拷贝产生的对象
T clonedObj = null;
try {
// 读取对象字节数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
// 分配内存空间,写入原始对象,生成新对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
// 返回新对象,进行类型转换
clonedObj = (T) ois.readObject();
ois.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return clonedObj;
}
}
当然,传入的类要实现Serializable.
今天的文章结束了~
Best Wish to you