# 豆持久性

> 原文： [https://docs.oracle.com/javase/tutorial/javabeans/advanced/persistence.html](https://docs.oracle.com/javase/tutorial/javabeans/advanced/persistence.html)

当 bean 的属性，字段和状态信息保存到存储并从存储中检索时，bean 具有持久性。组件模型提供了持久性机制，使组件的状态可以存储在非易失性位置以供以后检索。

使持久性成为可能的机制称为 _ 序列化 _。对象序列化意味着将对象转换为数据流并将其写入存储。任何使用该 bean 的 applet，应用程序或工具都可以通过反序列化“重新构建”它。然后该对象恢复到其原始状态。

例如，Java 应用程序可以序列化 Microsoft Windows 机器上的 Frame 窗口，序列化文件可以通过电子邮件发送到 Solaris 机器，然后 Java 应用程序可以将 Frame 窗口恢复到存在于该机器上的确切状态。 Microsoft Windows 机器。

任何使用该 bean 的 applet，应用程序或工具都可以通过 _ 反序列化 _“重构”它。

所有 bean 必须坚持下去。要保持，bean 必须通过实现 [`java.io.Serializable`](https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) （在 API 参考文档中）接口或 [`java.io.Externalizable`](https://docs.oracle.com/javase/8/docs/api/java/io/Externalizable.html) （在 API 参考文档中）接口来支持序列化。这些接口为您提供自动序列化和自定义序列化的选择。如果类的继承层次结构中的任何类实现`Serializable`或`Externalizable`，则该类是可序列化的。

## 可序列化的类

只要该类或父类实现`java.io.Serializable`接口，任何类都是可序列化的。可序列化类的示例包括`Component`，`String`，`Date`，`Vector`和`Hashtable`。因此，`Component`类的任何子类，包括`Applet`，都可以序列化。不支持序列化的值得注意的类包括`Image`，`Thread`，`Socket`和`InputStream`。尝试序列化这些类型的对象将导致`NotSerializableException`。

Java Object Serialization API 自动将 Serializable 对象的大多数字段序列化为存储流。这包括基本类型，数组和字符串。 API 不会序列化或反序列化标记为瞬态或静态的字段。

## 控制序列化

您可以控制 Bean 所经历的序列化级别。控制血清的三种方法是：

*   自动序列化，由`Serializable`接口实现。 Java 序列化软件序列化整个对象，瞬态和静态字段除外。
*   定制序列化。通过使用`transient`（或`static`）修改器进行标记，有选择地排除不希望序列化的字段。
*   自定义文件格式，由`Externalizable`接口及其两种方法实现。 Bean 以特定的文件格式编写。

## 默认序列化：可序列化接口

`Serializable`接口通过使用 Java 对象序列化工具提供自动序列化。 `Serializable`宣布没有方法;它充当标记，告诉对象序列化工具您的 bean 类是可序列化的。标记您的类`Serializable`意味着您告诉 Java 虚拟机（JVM）您已确保您的类将使用默认序列化。以下是使用`Serializable`界面的一些重要观点：

*   实现`Serializable`的类必须能够访问超类型的 _ 无参数构造函数 _。当从`.ser`文件“重构”对象时，将调用此构造函数。
*   如果已经在超类中实现了，则不需要在类中实现`Serializable`。
*   除静态和瞬态字段外的所有字段都是序列化的。使用`transient`修饰符指定不希望序列化的字段，并指定不可序列化的类。

## 使用瞬态关键字的选择性序列化

要在`Serializable`对象中从序列化中排除字段，请使用`transient`修饰符标记字段。

```
transient int status;

```

默认序列化不会序列化`transient`和`static`字段。

## 选择性序列化：writeObject 和 readObject

如果可序列化类包含以下两种方法之一（签名必须准确），则不会进行默认序列化。

```
private void writeObject(java.io.ObjectOutputStream out)
    throws IOException;
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException;

```

您可以通过编写自己的`writeObject`和`readObject`方法实现来控制更复杂对象的序列化。当需要序列化默认序列化无法处理的对象时，或者需要将数据添加到非对象数据成员的序列化流时，需要对需要序列化的内容进行更好的控制时实现`writeObject`。实现`readObject`以重建您使用`writeObject`编写的数据流。

## Externalizable 接口

当您需要完全控制 bean 的序列化时（例如，在编写和读取特定文件格式时），请使用`Externalizable`接口。要使用`Externalizable`接口，需要实现两种方法：`readExternal`和`writeExternal`。实现`Externalizable`的类必须具有无参数构造函数。