Java之序列化与反序列化
前言
Java序列化是指把Java对象转换为字节序列的过程,反序列化是指把字节序列恢复为Java对象的过程。
一、序列化与反序列化的作用
序列化:在传递和保存对象时,保存对象的完整性和可传递性。对象转换为有序字节流,可以在网络上传输或者保存在本地文件(一般为json/xml文件)。
反序列化:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。
二、序列化和反序列化的优缺点
1.优点
- 将对象转为字节流储存在硬盘上,当jvm停机的时候,字节流还会在硬盘上等待下一次jvm启动,把序列化对象,通过反序列化转为原来的对象。因为它是永久性保存对象的,序列化的二进制序列能够减少存储空间。
- 序列化为字节流形式的对象可以进行网络传输。
- 通过序列化可以在进程间传递对象。
2.缺点
- 无法跨语言
- 序列化后流的长度比通过缓冲区处理要大得多
- 序列化性能太低
三、使用场景
- 分布式传递对象或者网络传输,需要序列化
- 调用其他jvm的方法,返回自己jvm上进行处理
- 序列化可以保持对象的状态
- 数据传输并复原
四、注意事项
- Java序列化的方式
- 实现Serializable接口:可以定义writeObject、readObject、writeReplace、readResolve方法,会通过发射调用。
- 实现Externalizable接口:需要实现writeExternal和readExternal方法。
-
序列化ID问题
虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的店是两个类的序列化ID是否一致。 -
静态字段不会序列化
序列化时不会保存静态变量,这是因为序列化保存的是对象的状态,静态变量属于类的状态。 -
transient
transient代表对象的临时数据。如果不想让对象中的某个成员被序列化,可以在定义时加上transient。
transient修饰的成员反序列化后将赋予默认值,0或null。 -
父类的序列化
当父类实现序列化,子类自动实现序列化。当子类实现Serializable接口,父类也需实现该接口。 -
一个对象的实例变量引用其他对象,序列化该对象时也把引用对象序列化
-
不是所有对象都能序列化
- 由于安全方面。比如当一个对象是private,对于一个要传输的对象写到文件或者进行RMI传输等,在序列化过程中,对象的private是不受保护的。
- 由于资源分配。如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新资源分配。
- 序列化解决深拷贝问题
如果一个对象的成员变量是一个对象,拿这个对象的数据成员也会被保存,这是能用序列化解决深拷贝的重要原因。
注:前面提到序列化后长度会变大,请记住序列化机制只保存对象的类型信息,属性的类型信息和属性值,和方法没有什么关系,就算对象有再多的方法,序列化内容也不会增加任何东西