1

私はObjectOutputStream のドキュメントを読み、シリアライゼーションについて読んでいますが、混乱しています。それは次のように述べています

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

参照共有メカニズムの意味は何ですか? また、次のようにも述べています。

列挙型定数は、通常のシリアライズ可能オブジェクトまたは外部化可能オブジェクトとは異なる方法でシリアライズされます。enum 定数のシリアル化された形式は、その名前だけで構成されます。定数のフィールド値は送信されません。列挙型定数をシリアル化するために、ObjectOutputStream は、定数の名前 method によって返される文字列を書き込みます。他のシリアル化可能オブジェクトまたは外部化可能オブジェクトと同様に、列挙型定数は、シリアル化ストリームに後で現れる後方参照のターゲットとして機能できます。

私が考えることができる理由の 1 つは、Enum フィールドは定数であるため、シリアル化されないことです。では、Enum をシリアル化する必要がある場合、正確にはどうすればよいでしょうか? もう 1 つ、状態をシリアル化できない場合、コンパイラが Enum のシリアル化を制限しないのはなぜですか? 列挙定数が後方参照のターゲットとして機能できるという意味は何ですか?

この疑問を明確にするのを手伝ってください。ありがとう。

4

3 に答える 3

3

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

これは、サイクルを含むオブジェクト グラフをシリアル化できることを意味します。

つまり、次のグラフをシリアライズする場合:

A --> B --> C --> A (C は A を指します)。

A をシリアル化すると、次のようになります。

  1. シリアル化 A
  2. A のオブジェクト ツリーをたどって B を見つける
  3. B の単純なフィールドをシリアライズする
  4. B のオブジェクト ツリーをたどって C を見つける
  5. C の単純なフィールドをシリアライズする
  6. C のオブジェクト ツリーをたどって A を見つける
  7. ストリームの下流にある Aにポインターを送信する

これを行わないと、A をシリアル化すると無限ループが発生します。

列挙型定数は、通常のシリアライズ可能オブジェクトまたは外部化可能オブジェクトとは異なる方法でシリアライズされます。enum 定数のシリアル化された形式は、その名前だけで構成されます。定数のフィールド値は送信されません。列挙定数をシリアル化するために、ObjectOutputStream は、定数の name メソッドによって返された文字列を書き込みます。

列挙型は定数であるため、どこで使用されても常に同じ状態であると想定されるため、列挙型の状態を送信する必要はありません。したがって、受信側が列挙型を受信すると、その側でその列挙型のオブジェクトを検索し、どちらかの側の 2 つの列挙型が異なる状態になる可能性がある場合でも、それを列挙型として返します。

于 2013-08-02T09:52:44.710 に答える
1

単一のオブジェクトへの複数の参照は、参照共有メカニズムを使用してエンコードされます

オブジェクト グラフがある場合、そのグラフ内のオブジェクトへの参照の数に関係なく、そのグラフ内の各オブジェクトは 1 回だけシリアル化されます。たとえば、次のようなグラフにオブジェクト A、B、C、および D があるとします。

ここに画像の説明を入力

オブジェクト D は、パス A -> B -> D および A -> C -> D を介して到達できますが、オブジェクトのシリアル化メカニズムは、2 番目のパスを介してオブジェクト D に到達したときに、オブジェクト D を既にシリアル化していることを認識するのに十分なほどスマートです。そのため、再度シリアル化しようとしません。オブジェクト グラフは参照用語でシリアル化されており、各オブジェクトにはそのプリミティブと参照だけが格納されているのではないかと思います (ただし、十分に詳しく調べたことはありません)。これは、シリアル化されたオブジェクト グラフのサイズを最小化するだけでなく、循環参照を処理する上でも重要です。

あなたが言うように、Enumは定数であることを意図しているため、Enum定数は通常のシリアライズ可能または外部化可能オブジェクトとは異なる方法でシリアライズされます。これを壊すことは可能ですが、ある JVM でシリアライズされた列挙が別の JVM でデシリアライズされたときに異なるように見えるようにすることは可能ですが、これはランタイム状態を列挙に追加した結果です。

于 2013-08-02T10:02:41.373 に答える