14

私は小さなソケットベースのプログラムを書いています。クラス ModelEvent を使用して、ソケットを介して情報を渡しています。ModelEvent 内には、タイプ (Object) の変数オブジェクトがあります。

オブジェクト自体は、いくつかの値を持つ 2D 配列です。

object[1][2] = 2;
ModelEvent event = new ModelEvent("allo", object);
dispatchEvent(event);

object[2][3] = 2;
ModelEvent event2 = new ModelEvent("you", object);
dispatchEvent(event2);

配列オブジェクトが値 1 で満たされているとしましょう。最初のイベント (イベント) がクライアントによって受信され、データは正しいです。データを介して送信された 2 番目のイベントが正しくありません。そのデータは、最初のディスパッチと同じです。「allo」と「you」は、同じイベントを 2 回読んでいないかどうかを確認するためのもので、答えはそうではありません。文字列は正しいですが、オブジェクトが更新された場合はイベントではありません。2 番目のイベントを送信する前に配列を反復処理して、サーバー側で更新されているかどうかを確認します。ただし、クライアント側では、イベント自体が変更されても、最初のディスパッチと同じままです。

4

2 に答える 2

27

を参照してくださいObjectOutputStream.reset

リセットは、ストリームに既に書き込まれているオブジェクトの状態を無視します。状態は新品同様にリセットされますObjectOutputStream。ストリームの現在のポイントはリセットとしてマークされているため、対応ObjectInputStreamするポイントは同じポイントでリセットされます。以前にストリームに書き込まれたオブジェクトは、既にストリームにあるとは見なされません。それらは再びストリームに書き込まれます。

/* prevent using back references */
output.reset();
output.writeObject(...);

同じオブジェクトを書き込む前にリセットを呼び出して、更新された状態がシリアル化されるようにします。それ以外の場合は、古い状態の以前に書き込まれたオブジェクトへの後方参照を使用するだけです。

または、代わりに次のように使用することもできObjectOutputStream.writeUnsharedます。

「非共有」オブジェクトを に書き込みますObjectOutputStream。このメソッドはwriteObject、(以前にシリアル化されたインスタンスを指す逆参照ではなく) 指定されたオブジェクトをストリーム内の新しい一意のオブジェクトとして常に書き込むことを除いて、 と同じです。

具体的には:

  • writeUnshared を介して書き込まれたオブジェクトは、オブジェクトが以前に書き込まれたかどうかに関係なく、新しく出現したオブジェクト (まだストリームに書き込まれていないオブジェクト) と同じ方法で常にシリアル化されます。

  • を使用して、以前に writeUnshared で書き込まれたオブジェクトを書き込む場合writeObject、以前の writeUnshared 操作は、別のオブジェクトの書き込みであるかのように扱われます。つまり、 へのObjectOutputStream呼び出しによって書き込まれたオブジェクト データへの後方参照は決して生成されませんwriteUnshared

を介してオブジェクトを書き込むことwriteUnshared自体は、逆シリアル化されたときにオブジェクトへの一意の参照を保証しませんが、1 つのオブジェクトをストリーム内で複数回定義できるためreadUnshared、レシーバーによる への複数回の呼び出しが競合しません。上記の規則は、 で記述されたベースレベル オブジェクトにのみ適用され、writeUnsharedシリアル化されるオブジェクト グラフ内の推移的に参照されるサブオブジェクトには適用されないことに注意してください。

output.writeUnshared(...);

これを と結合することをお勧めしObjectInputStream.readUnsharedます。

から「非共有」オブジェクトを読み取りますObjectInputStream。このメソッドは readObject と同じですが、この呼び出しによって取得されたデシリアライズされたインスタンスへの後続の呼び出しreadObjectおよび追加の参照が返されないようにする点が異なります。readUnshared

具体的には:

  • readUnshared逆参照 (以前にストリームに書き込まれたオブジェクトのストリーム表現) を逆シリアル化するために が呼び出された場合、ObjectStreamExceptionがスローされます。
  • 正常readUnsharedに返された場合、デシリアライズされたストリーム ハンドルへの後方参照をデシリアライズしようとするreadUnsharedと、ObjectStreamExceptionがスローされます。

経由でオブジェクトを逆シリアルreadUnshared化すると、返されたオブジェクトに関連付けられたストリーム ハンドルが無効になります。これ自体は、によって返される参照readUnsharedが一意であることを常に保証するわけではないことに注意してください。逆シリアル化されたオブジェクトは、readResolve他のパーティに表示されるオブジェクトを返すメソッドを定義するか、readUnshared がストリーム内の他の場所または外部手段を通じて取得可能なClassオブジェクトまたは定数を返す場合があります。enum逆シリアル化されたオブジェクトがメソッドを定義し、readResolveそのメソッドの呼び出しが配列をreadUnshared返す場合、その配列の浅いクローンを返します。readObjectこれにより、返された配列オブジェクトが一意であり、 の呼び出しまたは readUnshared で2 回目に取得できないことが保証されます。ObjectInputStream、基になるデータ ストリームが操作されている場合でも。

obj = input.readUnshared();
于 2012-09-09T17:20:32.833 に答える
4

dispatchEvent コードは表示されませんが、あなたが書いたものから、次のように推測します: 同じオブジェクトを書きます (状態のみが変更されます)。これは、参照のみを 2 回書き込むことを意味します。Java出力ストリームドキュメントで確認できます(パフォーマンス用)。

書き込みごとに新しいオブジェクトを作成する writeUnshared() を使用する必要があります。

リセットが提案されたようです。これで同じ結果が得られますが、パフォーマンスに影響があります。

于 2012-09-09T17:22:06.047 に答える