为什么要序列化
在内存中,一个对象是不连续的,需要传输的时候需要将一个对象转换成连续的二进制流。
如何序列化?
public class Test implements Serializable {
private int i = 1;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
JSON
字符串
{"i":1}
二进制
[123, 34, 105, 34, 58, 49, 125]
占用字节数
占用了7个字节
缺点
- 没有记录对象的class 反序列化无法区分 int long等
优点
- 占用字节数一般
- 阅读性高
- 无关语言
JDK
实现Serializable
,可以自己重写readObject
,writeObject
方法,自定义序列化
十六级制
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: AC ED 00 05 73 72 00 13 74 65 73 74 2E 73 65 72 ,m..sr..test.ser
00000010: 69 61 6C 69 7A 65 2E 54 65 73 74 00 00 00 00 00 ialize.Test.....
00000020: 00 00 01 02 00 01 49 00 01 69 78 70 00 00 00 01 ......I..ixp....
阅读
第1部分是序列化文件头
- AC ED:STREAM_MAGIC序列化协议
- 00 05:STREAM_VERSION序列化协议版本
- 73:TC_OBJECT声明这是一个新的对象
第2部分是要序列化的类的描述,在这里是SerializableObject类
- 72:TC_CLASSDESC声明这里开始一个新的class
- 00 13:十进制的19,表示class名字的长度是19个字节
- 74 65 73 ... 65 73 74:表示的是“test.serialize.Test”这一串字符
- 00 00 00 00 00 00 00 01:序列化版本,我们在这个类里面设置的值是1
- 02:标记号,声明该对象支持序列化
- 00 01:该类所包含的域的个数为1个
第3部分是对象中各个属性项的描述
- 02:表示该属性是一个基础类型
- 00 01十进制的1,表示属性名的长度
- 49:字符串“i”,属性名
第4部分是该对象父类的信息 这里为空
- 00 01:表示没有父类(这个还需要确认下)
- 69 : (这个还需要确认下)
- 78:TC_ENDBLOCKDATA,对象块结束的标志
- 70:TC_NULL,说明没有其他超类的标志
第5部分输出对象的属性项的实际值
00 00 00 01:属性值 i=1
占用字节数
很多,不统计了
缺点
- 序列化太大了
- 仅仅java
优点
- 记录了类名 ,反序列化不容易出错
Hessian2
十六级制
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: 43 13 74 65 73 74 2E 73 65 72 69 61 6C 69 7A 65 C.test.serialize
00000010: 2E 54 65 73 74 91 01 69 60 91 00 00 00 7A .Test..i`....z
这里仔细阅读了,参照:http://hessian.caucho.com/doc/hessian-serialization.html
和jdk删了一些版本号,然后优化了一些细节的存储。所以更省空间。