天天看点

Java序列化

 (1)序列化和反序列化其实就是对象和字节之间的转换。io之间进行数据传输,无论是网络io,还是文件io,都是以字节为单位。而对象要想传输就必须首先转化为字节序列进行传输,接收端从字节序列中反序列化得到对象。常见的应用就是网络编程中传输对象,文件系统中直接将对象信息保存在文件中,还有就是顶顶大名的rmi技术,其实就是调用远程对象的方法,这就涉及到对象的传输,其核心思想就是基于序列化机制。

(2)序列化机制的输入方法为objectinputstream的readobject()方法,输出为objectoutputstream的writeobject()方法。可以实现自己的readobject和writeobject方法,但必须是private,不是覆盖serializable的方法,而是序列化过程进行时会默认检查实现serializable接口的类是否定义上述两个方法,如果定义则调用这两个方法进行序列化和反序列化,否则采用默认的处理方式,通过这种方式可以控制序列化过程,应用就是传输前可以将一些字段加密,然后接收后进行解密。其实还可以实现externalizable,但是感觉这种方式没啥作用,通过自己实现readobject和wirteobject也可以完成同样的功能。

(3)序列化id的作用是保证序列化和反序列化时是同一个类,可以采用默认的1l,也可以采用随机生成的方法。这个id除了保证反序列化成功外,更重要的用途是版本更新时,通过更改序列id,让客户端程序反序列化该对象时失败,强制进行更新。

(4)序列化的过程就是将对象转化为对应的字节序列,这个转化算法并不是简单的将变量值记录下来,还记录了一些基本的类信息。序列化时,首先根据序列化的对象其包含的对象,其继承的父类,因为类的实例化首先是父类的实例化,然后才是其本身包括成员对象的实例化,因此通过解析这个对象图,依次检查是否实现serializable接口,进行序列化。父类可以不实现接口,子类从父类继承的对象也就不参与实例化,成员对象必须实现serializable接口。通过将变量加上transient关键字,可以指定某些变量不参与实例化,也就是其值不记录到字节流中,包括成员变量,如果该成员变量不参与序列化,其也就没必要实现serializable接口。序列化是将对象的信息转化为字节,对于静态变量这些属于类的存储单元,不进行序列化。

(5)序列化涉及到字节序列的存储优化,同样的对象序列化后,除了第一个对象的字节序列保存,后续保存的都是引用。因此无论相同的对象序列化多少次,反序列化得到的都是一个对象,当第一个对象序列化后,改变其值再序列化,改变后的值不会保存,因为字节序列已经保存了,后面只保存引用。

继续阅读