Java中的序列化和反序列示例
- 序列化是一种将对象的状态转换为字节流的机制。反序列化是相反的过程,其中字节流用于在内存中重新创建实际的Java对象。该机制用于持久化对象。
- 创建的字节流是平台无关的。因此,在一个平台上序列化的对象可以在另一个平台上反序列化。
-
为了使Java对象可序列化,我们实现了
java.io.Serializable
接口。 -
ObjectOutputStream
类包含writeObject()
方法为了序列化一个对象
public final void writeObject(Object obj)
throws IOException
ObjectOutputStream
类包含readObject()
方法为了反序列化一个对象
序列化的优势
- 为了保存/持久化一个对象的状态
- 为了在互联网中传递一个对象
- 只有那些实现了
java.io.Serializable
接口的类才能被序列化 Serializable
是一个标记接口(没有数据成员和方法)。它用于“标记”java类,以便这些类的对象可以获得某些功能。标记接口的其他例子有:Cloneable
和Remote
。
要点
- 如果一个父类已经实现了
Serializable
接口,那么子类不用再次实现,反之则不然。 - 只有非静态数据成员可以通过序列化过程保存的
- 静态数据成员和
transient
修饰的成员不能通过序列化存储。所以如果你不想序列化某个非静态的数据成员可以用transient
修饰。 - 当对象反序列化时,并不会调用对象的构造器
- 相关对象必须实现
Serializable
接口
SerialVersionUID
- 序列化运行时将版本号(
SerialVersionUID
)与Serializable
类相关联,该序列号在反序列化期间用于验证序列化对象的发送者和接收者是否已为该对象加载了与序列化兼容的类。如果接收者为对象加载的类的UID与相应发送者的类的UID不同,则反序列化将导致InvalidClassException
。Serializable
类可以通过声明字段名称来显式声明其自己的UID。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
- 它必须是被
static、final
修饰的长整型。 - 如果可序列化的类未明确声明
serialVersionUID
,则序列化运行时将根据该类的各个方面为该类计算一个默认值,如Java对象序列化规范中所述。 但是,强烈建议所有可序列化的类显式声明serialVersionUID
值,因为其计算对可能随编译器实现而变化的类详细信息高度敏感,任何类更改或使用不同的id都可能影响序列化的数据。 - 还建议对UID使用私有修饰符,因为它作为继承成员是没有用的。