Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaシリアライズにおけるオブジェクトグラフの仕組みと実装例

オブジェクトグラフ(object graph)とは、あるオブジェクトが別のオブジェクトへの参照を保持しているときに、それらが相互につながったオブジェクトの集合のことです。Javaでは、シリアル化対象のオブジェクトが他のオブジェクトへの参照を持っている場合、JVM(Java仮想マシン)はその参照先のオブジェクトも自動的にシリアル化します。つまり、起点となるオブジェクトを1つ書き出すだけで、そこから参照でつながるすべてのオブジェクトがまとめて保存されるのです。

サンプルコード

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class One implements Serializable{
    Two s2 = new Two();
}
class Two implements Serializable{
    Three s3 = new Three();
}
class Three implements Serializable{
    int i = 34;
    int j = 67;
}
public class Demo_Serialize{
    public static void main(String args[]) throws Exception{
        One s1 = new One();
        FileOutputStream my_fos = new FileOutputStream("abc.ser");
        ObjectOutputStream my_oos = new ObjectOutputStream(my_fos);
        my_oos.writeObject(s1);
        my_fos.close();
        my_oos.close();
        FileInputStream my_fis = new FileInputStream("abc.ser");
        ObjectInputStream my_ois = new ObjectInputStream(my_fis);
        One my_obj = (One) my_ois.readObject();
        my_fis.close();
        my_ois.close();
        System.out.println("Value of i after it is serialized is " + my_obj.s2.s3.i);
        System.out.println("Value of j after it is serialized is "+my_obj.s2.s3.j);
    }
}

実行結果

Value of i after it is serialized is 34
Value of j after it is serialized is 67

コードの解説

まず、「One」クラスがSerializableインターフェースを実装しており、その内部で「Two」クラスのインスタンス(s2)をフィールドとして保持しています。「Two」クラスも同様にSerializableインターフェースを実装し、さらにその中で「Three」クラスのインスタンス(s3)を保持しています。

「Three」クラスもSerializableインターフェースを実装しており、ここで2つのint型フィールド(iとj)が定義されています。これら3つのクラスによって、One → Two → Three という参照の連鎖、すなわちオブジェクトグラフが構成されています。

メインクラス「Demo_Serialize」のmainメソッドでは、最初に「One」クラスのインスタンスを生成し、FileOutputStreamとObjectOutputStreamを使用してオブジェクトをファイル「abc.ser」へ書き込みます。書き込みが完了したら、両方のストリームをクローズします。

続いて、FileInputStreamとObjectInputStreamを使って同じファイルからデータを読み込み、readObject()メソッドでデシリアライズを行います。読み込んだオブジェクトは「One」型にキャストされ、ストリームをクローズした後、復元されたオブジェクトのフィールド値(iとj)がコンソールに出力されます。

重要なポイント

この例からわかるように、「One」オブジェクトを1つシリアル化するだけで、その参照先である「Two」、さらにその先の「Three」まで、オブジェクトグラフ全体が自動的にシリアル化されています。これは、グラフに含まれるすべてのクラスがSerializableインターフェースを実装しているためです。

なお、もしオブジェクトグラフ内のどれか1つのクラスでもSerializableを実装していない場合、シリアル化の際にNotSerializableExceptionがスローされるので注意が必要です。

  1. Javaで抽象クラスのインスタンスは生成できる?参照変数の正しい使い方を解説

    結論から言うと、抽象クラス(abstract class)のオブジェクト(インスタンス)を直接生成することはできません。ただし、抽象クラス型の参照変数を作成することは可能です。この参照変数は、抽象クラスを継承した派生クラス(サブクラス)のオブジェクトを参照するために使われます。抽象クラスとは何か抽象クラスとは、実装の詳細を隠蔽し、機能の定義だけをユーザーに見せるための仕組みです。Javaの抽象クラスには、デフォルトの動作を実装したインスタンスメソッドを持たせることもできます。設計段階である程度の実装が確定していて、かつ一部の処理をサブクラスに委ねたい場合に、抽象クラスを選択するのが適切です。サ

  2. Javaのfinalクラスとは?継承を禁止する仕組みと使い方を徹底解説

    Javaにおいて、クラスにfinal修飾子を付けて宣言する最大の目的は、そのクラスがサブクラス化(継承)されることを防ぐことです。クラスがfinalとして宣言されると、どのクラスもそのクラスを継承できなくなり、finalクラスの機能や振る舞いを拡張・変更することが不可能になります。finalクラスの基本構文finalクラスの宣言は非常にシンプルです。クラス名の前にfinalキーワードを付けるだけです。public final class Test { // クラスの本体 }このように宣言されたTestクラスに対して、以下のような継承を試みるとコンパイルエラーが発生します。// コンパイ