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文件。 - 当通过文件、网络来读取序列化后的对象时,必须按实际写入的顺序读取。