English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Java

Java Flow Control

Java Array

Java Object-Oriented (I)

Java Object-Oriented (II)

Java Object-Oriented (III)

Manejo de excepciones en Java

Java List

Java Queue (queue)

Java Map collection

Java Set collection

Java Input/Output (I/O)

Java Reader/Writer

Other Java topics

Java 序列化

Java provides a mechanism for object serialization, in which an object can be represented as a byte sequence, which includes the data of the object, information about the object's type, and the types of data stored within the object.

After the serialized object is written to a file, it can be read from the file and deserialized, which means that the type information of the object, the data of the object, and the data types within the object can be used to create a new object in memory.

The entire process is independent of the Java Virtual Machine (JVM), which means that an object serialized on one platform can be deserialized on another completely different platform.

The ObjectInputStream and ObjectOutputStream classes are high-level data streams that include methods for deserializing and serializing objects.

The ObjectOutputStream class includes many write methods to write various data types, but there is an exception to this:

public final void writeObject(Object x) throws IOException

The above method serializes an object and sends it to the output stream. The similar ObjectInputStream class includes the following method for deserializing an object:

public final Object readObject() throws IOException, 
                                 ClassNotFoundException

该方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,你需要将它转换成合适的数据类型。

为了演示序列化在Java中是怎样工作的,我将使用之前教程中提到的Employee类,假设我们定义了如下的Employee类,该类实现了Serializable 接口。

public class Employee implements java.io.Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name
                           + " " + address);
   }
}

请注意,一个类的对象要想序列化成功,必须满足两个条件:

该类必须实现 java.io.Serializable 接口。

该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的示例是否能序列化十分简单,只需要查看该类有没有实现 java.io.Serializable 接口。

序列化对象

ObjectOutputStream 类用来序列化一个对象,如下的 SerializeDemo 实例示例化了一个 Employee 对象,并将该对象序列化到一个文件中。

该程序执行后,就创建了一个名为 employee.ser 的文件。该程序没有任何输出,但是你可以通过代码研读来理解程序的作用。

注意: 当序列化一个对象到文件时,按照 Java 的标准约定是给文件一个 .ser 扩展名。

import java.io.*;
 
public class SerializeDemo
{
   public static void main(String[] args)
   {
      Employee e = new Employee();
      e.name = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN = 11122333;
      e.number = 101;
      try
      {
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser);
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser);
      catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

反序列化对象

下面的 DeserializeDemo 程序示例了反序列化,/tmp/employee.ser 存储了 Employee 对象。

import java.io.*;
 
public class DeserializeDemo
{
   public static void main(String[] args)
   {
      Employee e = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser);
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      catch(IOException i)
      {
         i.printStackTrace();
         return;
      catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: "); + e.name);
      System.out.println("Address: "); + e.address);
      System.out.println("SSN: "); + e.SSN);
      System.out.println("Número: ") + e.number);
    }
}

El resultado de la compilación y ejecución del programa anterior es el siguiente:

Empleado deserializado...
Nombre: Reyan Ali
Dirección: Phokka Kuan, Ambehta Peer
SSN: 0
Número:101

Aquí debe prestar atención a los siguientes puntos:

try dentro del método readObject()/El bloque catch intenta capturar la excepción ClassNotFoundException. Para que un objeto pueda ser deserializado por JVM, debe poder encontrar el código byte de la clase. Si JVM no puede encontrar la clase durante el proceso de deserialización del objeto, se lanza una excepción ClassNotFoundException.

Nota, el valor de retorno del método readObject() se convierte en una referencia a Employee.

El valor de la propiedad SSN cuando el objeto se serializa es 111222333pero ya que el atributo es transitorio, no se envió el valor al flujo de salida. Por lo tanto, el atributo SSN del objeto Employee después de la deserialización es 0.