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

Java 基礎教程

Java 流程制御

Java 配列

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Java 異常処理

Java リスト(List)

Java Queue(キュー)

Java Map 集合

Java Set 集合

Java 入出力(I/O)

Java Reader/Writer

Java その他のトピック

Java シリアライズ

Java はオブジェクトのシリアライズメカニズムを提供しており、そのメカニズムでは、オブジェクトがデータバイトシーケンスとして表現され、そのシーケンスにはオブジェクトのデータ、オブジェクトに関する情報、オブジェクト内のデータのタイプが含まれています。

シリアライズされたオブジェクトをファイルに書き込んだ後、ファイルから読み出し、それを反シリアライズすることができます、つまり、オブジェクトのタイプ情報、オブジェクトのデータ、オブジェクト内のデータタイプを使用して、メモリ内に新しいオブジェクトを作成できます。

その全過程は Java 虚拟机 (JVM) 独立です、つまり、あるプラットフォームでシリアライズされたオブジェクトは、完全に異なるプラットフォームで反シリアライズできます。

ObjectInputStream クラスと ObjectOutputStream クラスは高レベルのデータストリームで、オブジェクトのシリアライズとデシリアライズメソッドを含んでいます。

ObjectOutputStream クラスには様々なデータタイプを書き込むための多くのメソッドがありますが、特別なメソッドが一つあります:

public final void writeObject(Object x) throws IOException

上記のメソッドはオブジェクトをシリアライズし、それをオブジェクトストリームに送信します。似た ObjectInputStream クラスには以下のオブジェクトの反シリアライズメソッドがあります:

public final Object readObject() throws IOException, 
                                 ClassNotFoundException

このメソッドはストリームから次のオブジェクトを取得し、そのオブジェクトをデシリアライズします。そのため、それを適切なデータ型に変換する必要があります。

Javaでシリアライズがどのように動作するかを示すために、前のチュートリアルで言及したEmployeeクラスを使用します。以下のようにSerializableインターフェースを実装したEmployeeクラスを定義しています。

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);
   }
}

クラスのオブジェクトがシリアライズできるためには、以下の2つの条件を満たす必要があります:

このクラスは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("シリアライズされたデータは以下に保存されています:" /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("Number: "} + e.number);
    }
}

上記のプログラムのコンパイルおよび実行結果は以下の通りです:

デシリアライズされた Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

以下のポイントに注意してください:

readObject() メソッド内の  try/catch ブロックは ClassNotFoundException 异常をキャッチしようと試みます。JVM がオブジェクトを反序列化できる場合、オブジェクトのバイトコードを見つけることができます。JVM が反序列化の過程でそのクラスを見つけることができなかった場合、ClassNotFoundException 异常が投げられます。

注意、readObject() メソッドの返値は Employee リファレンスに変換されます。

オブジェクトがシリアライズされる際に、属性 SSN の値は 111222333、しかし属性が一時的であるため、その値は出力ストリームに送信されていません。したがって、反序列化後の Employee オブジェクトの SSN 属性は 0 です。