Java-シリアライゼーション
Java は、オブジェクトのデータだけでなく、オブジェクトの型とオブジェクトに格納されているデータの型に関する情報を含むバイトのシーケンスとしてオブジェクトを表すことができる、オブジェクトのシリアル化と呼ばれるメカニズムを提供します。
シリアル化されたオブジェクトがファイルに書き込まれた後、そのオブジェクトをファイルから読み取って逆シリアル化できます。つまり、オブジェクトとそのデータを表す型情報とバイトを使用して、メモリ内にオブジェクトを再作成できます。
最も印象的なのは、プロセス全体が JVM に依存しないことです。つまり、あるプラットフォームでオブジェクトをシリアライズし、まったく別のプラットフォームでデシリアライズできます。
クラス ObjectInputStream および ObjectOutputStream オブジェクトをシリアライズおよびデシリアライズするためのメソッドを含む高レベルのストリームです。
ObjectOutputStream クラスには、さまざまなデータ型を書き込むための多くの書き込みメソッドが含まれていますが、特に 1 つのメソッドが際立っています −
public final void writeObject(Object x) throws IOException
上記のメソッドは、オブジェクトをシリアル化し、出力ストリームに送信します。同様に、ObjectInputStream クラスには、オブジェクトを逆シリアル化するための次のメソッドが含まれています -
public final Object readObject() throws IOException, ClassNotFoundException
このメソッドは、ストリームから次のオブジェクトを取得し、逆シリアル化します。戻り値は Object であるため、適切なデータ型にキャストする必要があります。
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 インターフェースを実装する必要があります。
<リ>クラス内のすべてのフィールドはシリアライズ可能である必要があります。フィールドがシリアル化できない場合は、transient とマークする必要があります .
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 プログラムは、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 は、オブジェクトの逆シリアル化中にクラスを見つけられない場合、ClassNotFoundException をスローします。
<リ>readObject() の戻り値が Employee 参照にキャストされていることに注意してください。
<リ>オブジェクトがシリアル化されたときの SSN フィールドの値は 11122333 でしたが、このフィールドは一時的なものであるため、この値は出力ストリームに送信されませんでした。逆シリアル化された Employee オブジェクトの SSN フィールドは 0 です。
Java