Java中序列化与反序列化
在程序运行的过程中,所有的对象都是保存在内存中的,这意味着当程序运行结束的时候,操作系统会把分配给对象的内存全部回收。
那有什么办法可以把对象存储起来?
序列化就可以帮我们做到,序列化是将对象的状态信息转换成可取的格式的过程,可以存储为文件,或者透过网络发送数据时进行编码的过程,可以是字节或是XML等格式。其相反的过程就被称为反序列化。
Java中准备了 Serializable
、Externalizable
两个接口(需要序列化的类必须实现这两个接口其一),和 ObjectOutputStream
、ObjectInputStream
两个类来帮助开发者实现序列化与反序列化。
Serializable Code
只需在需要序列化的类上实现 Serializable
接口,即可通过 ObjectOutputStream
实现序列化到文件系统中。
输出结果为 Person{name='MrXieXie', age=null, password='null'}
注意:序列化到文件后,将 password
的值重置为 null
。
可以看出在 Serializable
,静态变量还有被 transient
标注的变量不会被序列化。
那么是不是所有的静态变量和被 transient
标注的变量就不会被序列化呢?让我们来看一下 Externalizable
接口。
Externalizable Code
使用 Externalizable
实现序列化要比 Serializable
复杂一丢丢,需要实现 writeExternal
和 readExternal
方法,这两个方法会在序列化和反序列化时调用。
需要注意的是,该接口需要调用被序列化类的无参构造器,若不提供则会抛出异常 java.io.InvalidClassException: cn.mrxiexie.serializable.Car; no valid constructor
输出结果为 Car{name='MrXieXie', brand='MrXieXie', price=1234567.89}
注意:序列化到文件后,将 price
的值重置为 null
。
可以看出即使是静态变量和被 transient
标注的变量还是会被序列化。原因很简单,Serializable
接口是自动序列化,当发现有 transient
标注的变量时则不序列化该变量,而 Externalizable
接口则是需要在 writeExternal
方法中指定需要序列化的变量。