次に例を示します。オブジェクトAには、オブジェクトAを含むオブジェクトCを含むオブジェクトBが含まれています。
オブジェクトAは正しくシリアル化されますか?
ここでのコメント#9は、機能しないことを示しています。
対照的に、XStreamは、循環参照を処理することを示します。
はい、デフォルトのJavaシリアル化は循環参照に対して機能します。オブジェクトCをシリアル化すると、フィールドには、再度シリアル化するのではなく、すでにシリアル化されているオブジェクトAへの後方参照が含まれます。
はい、Javaシリアル化は循環参照に対して機能します。Javaシリアル化で何ができるかを理解するのに役立つ詳細については、こちらをお読みください。
はい、そうです。
私はこれを非常に非常に簡単なテストで行い、少なくともシリアル化を完了しました。私はそれが正しいと思います、しかしあなたはいくつかの余分な行でそれをチェックすることができます。
import java.io.*;
class A implements Serializable { B b; }
class B implements Serializable { C c; }
class C implements Serializable { A a; }
class Test {
public static void main( String [] args ) throws IOException {
A a = new A();
a.b = new B();
a.b.c = new C();
a.b.c.a = a;
new ObjectOutputStream( new ByteArrayOutputStream( ) ).writeObject( a );
System.out.println("It works");
}
}
オブジェクトをXMLにシリアル化すると、実際に参照を直接表示できます。子オブジェクトは一度だけシリアル化されます。すでにシリアル化されている子オブジェクトへの(シリアル化された構造内の任意の場所での)参照は、ファイル内のそのオブジェクトを指すだけです。
ただし、循環参照のシリアル化は少し面倒になる可能性があるため、可能であれば回避することをお勧めします。
はい-大きな注意点が1つあります。オブジェクトグラフにサイクルが含まれている場合、writeReplace/readResolveを使用することはできません。その理由はここで説明されています。
これは、一般的な場合、循環オブジェクトグラフがJoshBlochのSerializationProxyパターンの使用と互換性がないことを意味します。オブジェクトグラフの子孫ノードの構造について十分に理解している場合は、これを回避して、シリアル化時に逆参照を削除し、逆シリアル化時にそれらを置き換えることができます。しかし、それは一般的には不可能です。この問題は、JDKのバグレポートで何度か発生していますが、肩をすくめることがありました。デフォルトのJavaシリアル化の脆弱性を考えると、この態度はかなり苛立たしいものだと思います。困難な作業である独自の一般的なオブジェクトシリアル化ソリューションを実装する必要がありますが、オープンソースの代替手段が存在します。
私が出くわしたもので、かなり高品質のように見えるのは、EsotericSoftwareのKryoです。