相互に参照する2つのオブジェクトをシリアライズおよびデシリアライズするとどうなりますか?


15

より明確にするために、これは簡単な例です。

class A implements Serializable { public B b; }
class B implements Serializable { public A a; }
A a = new A();
B b = new B();
a.b = b;
b.a = a;

では、aオブジェクトとbオブジェクトをファイルにシリアル化し、そのファイルから逆シリアル化するとどうなりますか?

4つのオブジェクト、それぞれ2つを取得すると思った。同一のオブジェクトですが、異なるインスタンス。

しかし、他に何かあるのか、それとも正しいのか間違っているのかはわかりません。

答える必要のある技術がある場合は、Javaに基づいて考えてください。

ありがとうございました。

回答:


25

Javaはストリームに書き込まれたオブジェクトを追跡し、後続のインスタンスは実際のシリアル化されたオブジェクトではなくIDとして書き込まれます。

したがって、たとえば、ストリームにインスタンス "a"を書き込むと、ストリームはそのオブジェクトに一意のIDを与えます( "1"としましょう)。「a」のシリアル化の一部として、「b」をシリアル化する必要があり、ストリームは別のID(「2」)を与えます。次にストリームに「b」を書き込んだ場合、書き込まれるのは実際のオブジェクトではなくIDだけです。

入力ストリームは逆に同じことを行います。ストリームから読み取る各オブジェクトに対して、出力ストリームと同じアルゴリズムを使用してID番号を割り当て、そのID番号はマップ内のオブジェクトインスタンスを参照します。IDを使用してシリアル化されたオブジェクトを見つけると、マップから元のインスタンスを取得します。

これは、APIドキュメントで説明されている方法です。

単一のオブジェクトへの複数の参照は参照共有メカニズムを使用してエンコードされるため、オブジェクトのグラフは元のオブジェクトが書き込まれたときと同じ形状に復元できます。

この動作により問題が発生する可能性があります:ストリームは各オブジェクトへのハード参照を保持するため(IDをいつ置換するかがわかるため)、ストリームに多くの一時オブジェクトを書き込むとメモリが不足する可能性があります。これを解決するには、を呼び出しreset()ます。


そのため、逆シリアル化後に元の状態に戻りますか?相互参照を使用したシリアル化の前ですか?
Seregwethrin

1
はい、相互に参照する2つのオブジェクトのみになります。
12

1
Javaがこれを自動的に処理するとは信じられません。感銘を受けました
ランチャー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.