基于序列化的深复制
来源:互联网 发布:2016淘宝刷单技巧 编辑:程序博客网 时间:2024/05/18 03:57
复制对象 or 复制引用
在java中,下面代码常常见到
Person p = new Person("cx"); Person p1 = p; System.out.println(p); System.out.println(p1);
执行Person p1 = p指令后真正能达到我们期望的效果吗?
Person@549f9afbPerson@549f9afb
可以看到两个输出对象的地址都是一样的,所以这样的写法我们一定需要注意。
java中的clone
在java中使用clone必须要遵守以下几点。
1.在派生类中覆盖基类的clone()方法,并声明为public。(Object类中的clone()方法是protected的)。在子类重写的时候,可以扩大访问修饰符的范围。
2..在派生类的clone()方法中,调用super.clone()。因为在运行时刻,Object类中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
3.在派生类中实现Cloneable接口。
Person类如下:
public class Person implements Cloneable{ private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Object clone() throws CloneNotSupportedException { return (Person)super.clone(); }}
然后就可以使用clone方法了,代码如下:
Person p = new Person("cx"); Person p1 = (Person) p.clone(); System.out.println(p); System.out.println(p1);
这样的话输出就是2个不同的对象了
@3a780024@1c515979
不过Object.clone()方法只是浅复制,如果两个Person对象的name的地址值相同, 说明两个对象的name都指向同一个String对象, 也就是浅拷贝, 而如果两个对象的name的地址值不同, 那么就说明指向不同的String对象, 也就是在拷贝Person对象的时候, 同时拷贝了name引用的String对象, 也就是深拷贝。验证代码如下:
Person p = new Person("cx");Person p1 = (Person) p.clone();System.out.println(p.getName()==p1.getName());
运行结果为:
true
java序列化与反序列化
Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。
1)JDK类库中序列化API
java.io.ObjectOutputStream:表示对象输出流
它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream:表示对象输入流
它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。
2)实现序列化的要求
只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常
基于序列化的深复制
将一个对象转化为字节数组,然后在将字节数组转为对象,这2个对象为是同一个对象吗?当然不是,想一下,如果将一个对象序列化后传输到另一个应用中,然后另一个应该此字节数组反序列化后会是一个对象吗?这2个对象都不在同一个jvm中,肯定不会是同一个对象了。同理,将对象转为了字节数组放入输出流中,原对象的地址还是会存在jvm中的,然后从流中读出字节数组,转为为新的对象。其实最主要的方式是ObjectInputStream.readObject(),这个方法读取流转为对象的时候会根据从输入流中解析出来的ObjectStreamClass再构造一个新的ObjectStreamClass对象,在构造方法里边会查找本地(找不到就构造)一个本地对象的描述信息。在创建本地对象描述信息对象的时候,会递归创建超类的描述信息对象。所以新的对象是递归newInstance出来的。
Person类如下:
public class Person implements Serializable{ private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
序列化实现clone的代码如下:
public class CloneUtils { public static <T extends Serializable> T clone(T obj) { T clonedObj = null; ObjectInputStream ois = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ois = new ObjectInputStream(bais); clonedObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != ois) { ois.close(); } } catch (IOException e) { e.printStackTrace(); } } return clonedObj; }}
测试代码如下:
Person p = new Person("cx"); Person p1 = CloneUtils.clone(p); System.out.println(p1.getName()==p.getName());
测试结果如下:
false
- 基于序列化的深复制
- 用序列化实现List<T> 实例的深复制
- clone(序列化方式深复制)
- C# 序列化 复制
- 基于GTID的复制
- 基于Axis的自定义对象序列化
- 基于Axis的自定义对象序列化
- 基于Axis的自定义对象序列化
- MySQl复制---基于行的复制
- 原型模式的深浅复制和序列化
- java实现深复制:clone()及序列化
- java实现深复制:clone()及序列化
- java实现深复制:clone()及序列化
- 基于schema的流复制
- GoldenGate 基于日志的结构化数据复制备份软件
- 基于神经网络的序列标注
- 基于游戏消息数据的二进制序列化实现
- 基于OpenXES的XES序列化源码示例
- 455. Assign Cookies
- python(2)注释
- NDIS数据包环回
- ZOJ Seven Segment Display
- Java
- 基于序列化的深复制
- Failed to read auto-increment value from storage engine错误的处理方法
- Java 的布局管理器GridBagLayout的使用方法
- linux 停止命令运行
- Python基础—简介-变量-基本语法
- 使用dos命令对项目中编写好的包进行生成文档
- 对一只笔进行测试?
- Markdown语法
- ubuntu16.04不启动GUI