一、什么是对象序列化和对象反序列化?
序列化:把java对象转换为字节序列的过程。
反序列化:把字节序列恢复为java对象的过程。
二、使用场景、用途
1.持久化对象,保存对象的字节序列到本地文件中。
2.通过序列化对象在网络中传递数据。
3.通过序列化对象在进程间传递数据。
4.通过序列化对象实现分布式对象。例如RMI要利用对象序列化运行远程主机上的服务,与在本地主机上运行对象相同。
三、实现对象序列化的方法
1.实现Serializable接口,系统默认实现序列化。
2.实现Externalizable接口,需要自己定义序列化和反序列化过程,即实现接口中的readExternal()和writeExternal()方法。
四、如何实现对象在磁盘上的存取操作?
可以通过ObjectOutputStream中的writeObject(Object obj)和ObjectInputStream中的readObject(Object obj)来完成。
注意:以对象为单位进行文件写入时,该对象类型必须是可序列化的,否则会抛出NotSerializableException异常。
五、使用ObjectInputStream读取对象时为什么会发生StreamCorruptedException异常?
StreamCorruptedException是流中的控制信息不一致异常,当从对象流中读取的控制信息与内部一致性检查相冲突时,就会抛出此异常。
由于Serializable序列化机制实现时要求ObjectOutputStream对象和ObjectInputStream对象一一对应,即一个ObjectOutputStream对象输出的对象要使用一个ObjectInputStream对象读入。
六、对象中的成员哪些参与序列化?哪些不参与序列化?
1.参与序列化:属性,包括基本数据类型、数组以及其他对象的引用;类名。
2.不参与序列化:方法;static属性;transient属性。
七、如何自定义序列化和反序列化过程?
1.使用Serializable接口时,重写writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)方法;
注意:对于简单类型的属性,必须使用默认的writeInt(int i)、readInt(int i)等方法进行读写操作,而对于引用类型的属性,可以在writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)方法中使用writeObject()和readObject()进行读写。
另外,在文件或网络中读取属性时,读取顺序必须和写入顺序一致。
2.使用Externalizable接口时,重写接口中的readExternal()和writeExternal()方法。
八、在序列化类中添加serialVersionUID有什么作用?
如果没有显示定义serialVersionUID,那么编译时会自动生成一个serialVersionUID,而每次编译会生成不同的serialVersionUID,在反序列化对象
过程中会对serialVersionUID作比较,如果不相同就会发生InvalidClassException异常。
如果不希望通过编译来强制划分软件版本,即保证实现序列化接口的类能兼容以前版本,只需要显示定义一个serialVersionUID,但是这不是必要的。
九、当序列化遭遇继承时,如何正确处理对象序列化过程?
1.如果父类实现了Serializable接口或Externalizable接口,则其所有子类自动实现序列化。
注意:在实际操作中,如果只需要对子类进行序列化,直接将其父类实现序列化是不可取的,因为这样会强制所有子类具有序列化的能力。
2.如果父类没有实现序列化,而子类实现了序列化,此时在序列化过程中会抛出InvalidClassException异常。正确做法是为父类提供无参构造方法,并且在子类中显示定义序列化和反序列化过程。
十、常见的序列化协议有哪些?
xml,json,protobuf,Thrift和Avro
十一、序列化协议选型建议
1、对于公司间的系统调用,如果性能要求在100ms以上的服务,基于XML的SOAP协议是一个值得考虑的方案。
2、基于Web browser的Ajax,以及Mobile app与服务端之间的通讯,JSON协议是首选。对于性能要求不太高,或者以动态类型语言为主,或者传输数据载荷很小的的运用场景,JSON也是非常不错的选择。
3、对于调试环境比较恶劣的场景,采用JSON或XML能够极大的提高调试效率,降低系统开发成本。
4、当对性能和简洁性有极高要求的场景,Protobuf,Thrift,Avro之间具有一定的竞争关系。
5、对于T级别的数据的持久化应用场景,Protobuf和Avro是首要选择。如果持久化后的数据存储在Hadoop子项目里,Avro会是更好的选择。
6、由于Avro的设计理念偏向于动态类型语言,对于动态语言为主的应用场景,Avro是更好的选择。
7、对于持久层非Hadoop项目,以静态类型语言为主的应用场景,Protobuf会更符合静态类型语言工程师的开发习惯。
8、如果需要提供一个完整的RPC解决方案,Thrift是一个好的选择。
9、如果序列化之后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,Protobuf可以优先考虑。
参考资料:http://www.tuicool.com/articles/IVJFjiR