# 可序列化对象

> 原文： [https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html](https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html)

对于 _ 序列化 _，对象意味着将其状态转换为字节流，以便可以将字节流还原为对象的副本。 Java 对象是 _serializable_ ，如果它的类或其任何超类实现 `java.io.Serializable` 接口或其子接口， `java.io.Externalizable` 。 _ 反序列化 _ 是将对象的序列化形式转换回对象副本的过程。

例如， `java.awt.Button` 类实现 `Serializable` 接口，因此您可以序列化 `java.awt.Button` 对象并将该序列化状态存储在一份文件。稍后，您可以回读序列化状态并反序列化为 `java.awt.Button` 对象。

Java 平台指定序列化对象序列化的默认方式。 （Java）类可以覆盖此默认序列化，并定义自己的序列化该类对象的方式。 [对象序列化规范](https://docs.oracle.com/javase/8/docs/technotes/guides/serialization/index.html)详细描述了对象序列化。

对象序列化后，标识其类的信息将记录在序列化流中。但是，不记录类的定义（“类文件”）本身。系统负责对对象进行反序列化，以确定如何定位和加载必要的类文件。例如，Java 应用程序可能在其类路径中包含一个 JAR 文件，该文件包含序列化对象的类文件，或者使用存储在目录中的信息加载类定义，如本课程后面所述。

## 绑定可序列化对象

如果底层服务提供者支持该操作，您可以将可序列化对象存储在目录中，Oracle 的 LDAP 服务提供者也是如此。

以下示例调用 [`Context.bind`](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#bind-javax.naming.Name-java.lang.Object-) 将 AWT 按钮绑定到名称`“cn = Button”`。要将属性与新绑定相关联，请使用 [`DirContext.bind`](https://docs.oracle.com/javase/8/docs/api/javax/naming/directory/DirContext.html#bind-javax.naming.Name-java.lang.Object-javax.naming.directory.Attributes-) 。要覆盖现有绑定，请使用 [`Context.rebind`](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#rebind-javax.naming.Name-java.lang.Object-) 和 [`DirContext.rebind`](https://docs.oracle.com/javase/8/docs/api/javax/naming/directory/DirContext.html#rebind-javax.naming.Name-java.lang.Object-javax.naming.directory.Attributes-) 。

```
// Create the object to be bound
Button b = new Button("Push me");

// Perform the bind
ctx.bind("cn=Button", b);

```

然后，您可以使用 [`Context.lookup`](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#lookup-javax.naming.Name-) 读取对象，如下所示。

```
// Check that it is bound
Button b2 = (Button)ctx.lookup("cn=Button");
System.out.println(b2);

```

运行 [`this example`](examples/SerObj.java) 会产生以下输出。

```
# java SerObj
java.awt.Button[button0,0,0,0x0,invalid,label=Push me]

```

## 指定代码库

* * *

**注意：**此处描述的过程用于绑定目录服务中的可序列化对象，该目录服务遵循 [RFC 2713](http://www.ietf.org/rfc/rfc2713.txt) 中定义的模式。这些过程通常可能不适用于支持将可序列化对象与指定代码库绑定的其他命名和目录服务。

* * *

当序列化对象绑定在目录中时，如上例所示，从目录中读取序列化对象的应用程序必须能够访问反序列化对象所需的类定义。

或者，您可以在绑定对象时或者通过使用 [`DirContext.modifyAttributes`](https://docs.oracle.com/javase/8/docs/api/javax/naming/directory/DirContext.html#modifyAttributes-javax.naming.Name-int-javax.naming.directory.Attributes-) 添加属性时，在目录中记录带有序列化对象的 _ 代码库 _。您可以使用任何属性来记录此代码库，并让您的应用程序从目录中读取该属性并正确使用它。或者您可以使用指定的`“javaCodebase”`属性。在后一种情况下，Oracle 的 LDAP 服务提供程序将根据需要自动使用该属性加载类定义。 `“javaCodebase”`应该包含代码库目录或 JAR 文件的 URL。如果代码库包含多个 URL，则每个 URL 必须用空格字符分隔。

以下示例类似于绑定 `java.awt.Button` 的示例。它的不同之处在于它使用了用户定义的 `Serializable` 类， [``Flower` `](examples/Flower.java)，并提供`“javaCodebase”` ]属性包含 `Flower` 的类定义的位置。这是执行绑定的代码。

```
String codebase = ...;

// Create the object to be bound
Flower f = new Flower("rose", "pink");

// Perform the bind and specify the codebase
ctx.bind("cn=Flower", f, new BasicAttributes("javaCodebase", codebase));

```

运行 [`this example`](examples/SerObjWithCodebase.java) 时，必须提供安装类文件 `Flower.class` 的位置的 URL。例如，如果 `Flower.class` 安装在 Web 服务器 `web1` 上，在目录 `example / classes` 中，那么您将按如下方式运行此示例。

```
# java SerObjWithCodebase http://web1/example/classes/
pink rose

```

之后，您可以从类路径中删除 `Flower.class` 并运行任何查找或列出此对象的程序，而无需直接引用 `Flower` 类。如果您的程序直接引用 `Flower` ，那么您必须使其类文件可用于编译和执行。