深拷贝与Serializable简介
来源:互联网 发布:守望先锋mac能玩吗 编辑:程序博客网 时间:2024/06/11 02:49
上次我们说了Copy Constructor与clone()方法。谈到用拷贝构造函数和clone()方法来实现深拷贝会很麻烦。
那么有没有什么简单的方法来实现深拷贝呢?答案是有的,使用Java Serializable来实现深拷贝。
0. 数据类模型
什么是Serializable?我们来看下代码。
public interface Serializable {}
和之前的Cloneable是一个样子,与其说是一个接口,更像是一个属性。
我们建立一个嵌套深度为3的数据类。
注:这不是一个很好的面向对象的封装方式。此处只为缩减代码量。正式编程中请不要随便暴露类变量。
public class DataClass implements Serializable{ A a; double valueC; public DataClass(){ a = new A(); valueC = 1.05; } public DataClass(int valueA, float valueB, double valueC){ this.valueC = valueC; a = new A(valueA, valueB); } @Override public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("a = ").append(a.valueA).append("\n"); sb.append("b = ").append(a.b.valueB).append("\n"); sb.append("c = ").append(valueC).append("\n"); return sb.toString(); }}
其中,A类声明如下。
public class A implements Serializable { int valueA; B b; public A(){ valueA = 100; } public A(int valueA, float valueB){ this.valueA = valueA; b = new B(valueB); } @Override public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("a = ").append(valueA).append("\n"); sb.append("b = ").append(b.valueB).append("\n"); return sb.toString(); }}
B类声明如下。
public class B implements Serializable { float valueB; public B(){ valueB = 10f; } public B(float valueB){ this.valueB = valueB; }}
1. 深拷贝的实现
核心思想是用ObjectOutputStream来实现类的序列化;用ObjectInputStream来实现类的反序列化。
承载输出数据,以及接受的输入数据可以是:来自内存(ByteArrayOutputStream),来自文件(FileOutputStream),来自网络(Socket.getOutputStream())等。
因为深拷贝,我们写到内存里就可以,不需要对硬盘进行访问。
我们对2个DataClass和1个A类进行深拷贝。
实现代码如下。
DataClass serial1 = new DataClass(1,1.1f,1.2); DataClass serial2 = new DataClass(2,2.1f,2.2); A serial3 = new A(3,3.3f); //Serialize ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objectOut = new ObjectOutputStream(byteOut); objectOut.writeObject(serial1); objectOut.writeObject(serial2); objectOut.writeObject(serial3); objectOut.close(); byte[] buffer = byteOut.toByteArray(); //Deserialize ByteArrayInputStream byteIn = new ByteArrayInputStream(buffer); ObjectInputStream objectIn = new ObjectInputStream(byteIn); DataClass deSerial1 = (DataClass) objectIn.readObject(); DataClass deSerial2 = (DataClass) objectIn.readObject(); A deSerial3 = (A) objectIn.readObject(); System.out.println("Serialization:"); System.out.println("serial1:"); System.out.println(serial1); System.out.println("serial2:"); System.out.println(serial2); System.out.println("serial3:"); System.out.println(serial3); System.out.println("Deserialization:"); System.out.println("de-serial1"); System.out.println(deSerial1); System.out.println("de-serial2"); System.out.println(deSerial2); System.out.println("de-serial3"); System.out.println(deSerial3);
得到结果如下:
Serialization:serial1:a = 1b = 1.1c = 1.2serial2:a = 2b = 2.1c = 2.2serial3:a = 3b = 3.3Deserialization:de-serial1a = 1b = 1.1c = 1.2de-serial2a = 2b = 2.1c = 2.2de-serial3a = 3b = 3.3
进一步验证是否是深拷贝,我们进行如下修改。
serial1.a.b.valueB = 99.9f; System.out.println("serial1:"); System.out.println(serial1); System.out.println("de-serial1"); System.out.println(deSerial1);
得到结果如下。
serial1:a = 1b = 99.9c = 1.2de-serial1a = 1b = 1.1c = 1.2
可知,确实为深拷贝。
如果一个类的某些变量不想被序列化传递,可以声明为transient. 例如:
transient A a;
这样a这个变量就不会被序列化传递。
与此同时,带来的问题是,在反序列化的时候,对于一个类会抛出空指针异常(NullPointerException). 对于8大基础数据类型,则会被初始化为初始值(0, false等)
2. Serializable简介
你以为这就是Serializable的作用?不,这只是其冰山一角的功能罢了。Serializable最大的作用是可以将数据序列化后通过网络传输。相当于Java内建的XML, json.
以DataClass(1, 1.1f, 1.2)为例,其序列化格式如下(从左到右,从上到下):
其中h0和h1是句柄。
Serializable的其他用途我们下次再聊。
- 深拷贝与Serializable简介
- Java中的浅拷贝与深拷贝 + Serializable的传送链接
- Serializable 简介
- Serializable简介
- Serializable简介
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- “浅拷贝”与“深拷贝”
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 浅拷贝与深拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- “浅拷贝”与“深拷贝”
- 深拷贝与浅拷贝
- 浅拷贝与深拷贝
- Python006循环和遍历列表元组集合字典
- bzoj1123 求割点+乘法原理
- dyld: could not load inserted library 'dumpdecrypted.dylib' because no suitable image found.
- 排序算法之堆排序
- servlet下一个页面获取上一个页面的信息
- 深拷贝与Serializable简介
- overlay fs挂载及操作测试
- Android数据序列化方案研究
- IDL输出Excel中直接列分隔的txt文件方法
- 搜索手机里面的所有App,找到其中一个并启动
- Intel的视频硬编码方法
- <Java虚拟机>读书记录1-JVM运行时数据区域
- 求最大上升子序列
- Lua 基本语法