Java-シリアル化

Javaは、オブジェクトのデータだけでなく、オブジェクトのタイプとオブジェクトに格納されているデータのタイプに関する情報を含むバイトのシーケンスとしてオブジェクトを表すことができる、オブジェクトのシリアル化と呼ばれるメカニズムを提供します。

シリアル化されたオブジェクトがファイルに書き込まれた後、ファイルから読み取って逆シリアル化できます。つまり、オブジェクトとそのデータを表すタイプ情報とバイトを使用して、メモリ内にオブジェクトを再作成できます。

最も印象的なのは、プロセス全体がJVMに依存しないことです。つまり、オブジェクトを1つのプラットフォームでシリアル化し、まったく異なるプラットフォームで逆シリアル化できます。

クラス ObjectInputStream そして ObjectOutputStream オブジェクトをシリアル化および逆シリアル化するためのメソッドを含む高レベルのストリームです。

ObjectOutputStreamクラスには、さまざまなデータ型を書き込むための多くの書き込みメソッドが含まれていますが、特に1つのメソッドが際立っています。

public final void writeObject(Object x) throws IOException

上記のメソッドは、オブジェクトをシリアル化し、出力ストリームに送信します。同様に、ObjectInputStreamクラスには、オブジェクトを逆シリアル化するための次のメソッドが含まれています。

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

クラスが正常にシリアル化されるためには、2つの条件を満たす必要があることに注意してください-

  • クラスはjava.io.Serializableインターフェースを実装する必要があります。

  • クラス内のすべてのフィールドはシリアル化可能である必要があります。フィールドをシリアル化できない場合は、マークを付ける必要がありますtransient

Java Standard Classがシリアライズ可能かどうかを知りたい場合は、クラスのドキュメントを確認してください。テストは簡単です。クラスがjava.io.Serializableを実装している場合、それはシリアライズ可能です。そうでなければ、そうではありません。

オブジェクトのシリアル化

ObjectOutputStreamクラスは、オブジェクトをシリアル化するために使用されます。次のSerializeDemoプログラムは、Employeeオブジェクトをインスタンス化し、ファイルにシリアル化します。

プログラムの実行が完了すると、employee.serという名前のファイルが作成されます。プログラムは出力を生成しませんが、コードを調べて、プログラムが何をしているかを判断しようとします。

Note −オブジェクトをファイルにシリアル化する場合、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プログラムは、SerializeDemoプログラムで作成された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);
   }
}

これにより、次の結果が生成されます-

出力

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

注意すべき重要な点は次のとおりです-

  • try / catchブロックは、readObject()メソッドによって宣言されたClassNotFoundExceptionをキャッチしようとします。JVMがオブジェクトを逆シリアル化できるようにするには、クラスのバイトコードを見つけることができなければなりません。オブジェクトの逆シリアル化中にJVMがクラスを見つけることができない場合、JVMはClassNotFoundExceptionをスローします。

  • readObject()の戻り値がEmployee参照にキャストされていることに注意してください。

  • オブジェクトがシリアル化されたときのSSNフィールドの値は11122333でしたが、フィールドが一時的であるため、この値は出力ストリームに送信されませんでした。デシリアライズされたEmployeeオブジェクトのSSNフィールドは0です。