Serialization 简单小结

 
I. 什么是对象序列化
 
1. 我们要把对象保存到硬盘或者通过网络传输,就需要把对象状态保存下来,这个过程就是对象序列化或串行化。Java 中的序列化机制能够将一个实例对象的状态信息写入到一个字节流中,使其可以通过socket进行传输、或者持久化存储到数据库或文件系统中;然后在需要的时候,可以根据字节流中的信息来重构一个相同的对象。
2.对象序列化不是简单的把内存的内容拷贝出来。至少有下面的一些原因。
i. 如果对象还引用了其它对象,则引用的对象也需要保存下来。这时只是简单的保存引用对象的地址是没有意义的。这个地址只是在程序运行时才有意义,程序结束了无法根据地址找到引用对象的状态。这个过程是递归的,因为我们可能需要保存对象的对象的对象。
ii. 如果我们在不同系统之间使用同一个对象,比如把对象从windown传输到linux系统。这时对象应该以通用的形式保存或传输,异构系统才能知道如何恢复对象的状态而不必关心其它系统的实现细节。
 
II. Java怎样序列化

1.Java语言中,对象要能被序列化,需要实现Serialization。这个接口没有任何方法,只是一个标志性接口,表明这个对象可以被序列化。使用ObjectOutputStream的writeObject方法序列化一个对象;使用ObjectInputStream的readObject方法反序列化一个对象。

2.Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。需要序列化的对象应该显示的定义一个serialVersionUID,利用JDK的bin目录下的serialver.exe可以产生UID。如果没有显示定义,Java序列化机制会自动生成一个serialVersionUID,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID.

3. 序列化对象时,对象里引用的对象也要被序列化,但这个前提是引用的对象能被序列化。如果引用的对象不能被序列化,序列化终止,抛出NotSerializableException的异常。可以把不能序列化的引用的对象标志位transient。
4. 父类不能序列化,但是子类可以序列化,只要子类实现Serializable接口。这种情况,在反序列化时,父类必须提供默认参数,否则会报InvalidClassException异常。这也好理解。恢复一个对象,就是恢复其所有成员变量的值,而父类的成员变量的值不能恢复,就调用默认构造函数来初始化。

 

III. 自定义序列化过程

1. 如果不想使用Java提供的默认序列化方法(ObjectOutputStream的defaultWriteObject)或者反序列化方法(ObjectInputStream的defaulReadObject),则可以在需要序列化的类中实现writeObject或者readObject方法。
 
2. 可以实现Externalizable接口来完全控制序列化和反序列化过程和形式。
 
IV.避免序列化
1. 对象序列化时,任何方法和静态变量时不能被保存的。如果有些字段,比如密码,不需要被序列化,就用transient关键字标示这个字段。
 
2. 如果一个类不需要序列化,肯定是不实现Serializable接口。但是,如果这个类继承了一个可以序列化的类,这个类默认是可以序列化的,如果要阻止其被序列化,要么把所有的成员变量标志为transient, 要么就实现writeObject 和 readObject方法(实现它们,但它们是空办法),并且抛出NotSerializableException异常。
 
 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章