15.8.6 另一种自定义序列化机制
15.8.6 另一种自定义序列化机制
Java
还提供了另一种序列化机制,这种序列化方式完全由程序员决定存储和恢复对象数据。要实现该目标,Java
类必须实现Externalizable
接口。
Externalizable接口
Externalizable
接口里定义了如下两个方法。
方法 | 描述 |
---|---|
void writeExternal(ObjectOutput out) |
需要序列化的类实现这个writeExternal 方法来保存对象的状态。该方法
|
void readExternal(ObjectInput in) |
需要序列化的类实现这个readExternal() 方法来实现反序列化。该方法
|
DataInput
是ObjectInput
的父接口DataOutput
是ObjectOutput
的父接口
程序 实现Externalizable
接口自定义序列化
实际上,采用实现Externalizable
接口方式的序列化与前面介绍的自定义序列化非常相似,只是**Externalizable
接口强制自定义序列化**。
下面的Person
类实现了Externalizable
接口,并且实现了该接口里提供的两个方法,用以实现自定义序列化。
1 | import java.io.*; |
上面程序中的Person
类实现了java.io.Externalizable
接口,该Person
类还实现了readExternal
、writeExternal
两个方法,这两个方法除方法签名和readObject
、writeObject
两个方法的方法签名不同之外,其方法体完全一样。
序列化和反序列化方法相同
如果程序需要
- 序列化实现
Externalizable
接口的对象,一样调用ObjectOutputStream
的writeObject()
方法输出该对象即可; - 反序列化实现
Externalizable
接口的对象,则调用ObjectInputStream
的readObject()
方法
必须提供 public的 无参数构造器
需要指出的是,当使用Externalizable
机制反序列化对象时,程序会先使用public
的无参数构造器创建实例,然后才执行readExternal()
方法进行反序列化,因此实现Externalizable
的序列化类必须提供public
的无参数构造器。
表15.2两种序列化机制的对比
实现Serializable 接口 |
实现Externalizable 接口 |
---|---|
系统自动存储必要信息 | 程序员决定存储哪些信息 |
Java 内建支持,易于实现,只需实现该接口即可,无须任何代码支持 |
仅仅提供两个空方法,实现该接口必须实现g该接口的两个空方法 |
性能略差 | 性能略好 |
虽然实现Externalizable
接口能带来一定的性能提升,但由于实现Externalizable
接口导致了编程复杂度的增加,所以大部分时候都是采用实现Serializable
接口方式来实现序列化。
对象序列化需要注意的地方
关于对象序列化,还有如下几点需要注意。
- 对象的类名、实例变量(包括基本类型、数组、对其他对象的引用)都会被序列化;
- 方法、类变量(即
static
修饰的成员变量)、transient
实例变量(也被称为瞬态实例变量)都不会被序列化。
- 方法、类变量(即
- 实现
Serializable
接口的类如果需要让某个实例变量不被序列化,则可在该实例变量前加transient
修饰符,而不是加static
关键字。虽然static
关键字也可达到这个效果,但static
关键字不能这样用。 - 保证序列化对象的实例变量类型也是可序列化的,否则需要使用
transient
关键字来修饰该实例变量,要不然,该类是不可序列化的。 - 反序列化对象时必须有序列化对象的
class
文件。 - 当通过文件、网络来读取序列化后的对象时,必须按实际写入的顺序读取。