3

バックグラウンド

シリアル化機能がオーバーライドされておらず、がないクラスがありますが、serialVersionUIDそれでもシリアル化、保存、後で逆シリアル化されます。これは構成オブジェクトであり、構成を変更する場合、データは実際に構成UIから読み取られ、オブジェクトは通常「最初から」作成され、ストレージ用にシリアル化されます。使用する場合のみ、デシリアライズによってオブジェクトが作成されます。

これで、2つのフィールドがこのクラスに追加されました。これはシリアル化されるべきではありませんでしたが、...これはもちろん、いくつかの逆シリアル化の問題(デフォルトの逆シリアル化後にフィールドがnullのままになった場合のNullPointerException、クラスの不変条件の破損)につながり、構成を開くことで解決されますUIと構成の保存。これにより、オブジェクトの正しいシリアル化された形式が保存されます。

質問

ここで、保存された構成データからのオブジェクトの逆シリアル化で何が起こるか、これらの方法のいずれかでクラスを変更すると、簡単な修正が行われます。

  1. これらのフィールドを削除すると、保存されたデータは新しいバージョンであり、これらのフィールドが含まれていますか?
  2. これらのフィールドを一時的なものに変更すると、保存されたデータは新しいバージョンであり、これらのフィールドが含まれていますか?
  3. これらのフィールドを一時的なものに変更すると、保存されたデータは古いバージョンであり、これらのフィールドはありませんか?

これをより具体的にするために、追加されたフィールドが次のようになっているとしましょう。

private final Map<String, String> extraProperties = new HashMap<String, String>(); 

そして、これはこのクラスから削除されるか、private final transientフィールドに変更されます。

PS。カスタムシリアル化コードを追加する必要があり、その後、永続データと一時データを異なるクラスに分離するために、すべてをリファクタリングする必要があることを私に伝える必要はありません...

4

1 に答える 1

2

シリアル化したくないこれらの冗長なフィールドを削除 (または一時的に) します。次に、現在削除されている非一時フィールドが存在する古いバージョンのロードをデシリアライズしてみてください。serialVersionUIDクラスが異なるため、これはもちろんエラーになります。ただし、古いものと新しいものの両方をserialVersionUIDメッセージに含める必要があります。

クラスで定義private static long serialVersionUID =して、古い以前の値に設定します。ファイル内の余分なフィールドを持つクラス コンテンツが読み込まれ、これらの余分なフィールドの値は無視されます。

ただし、別の問題があります。おそらく、古いバージョンと新しいバージョンの 2 つの異なるタイプのファイルを保存しています。これらは異なる serialVersionUID を持つため、どちらか一方をロードできますが、両方をロードすることはできません。serialVersionUID は最終的なものですが、ここで説明されているように、別の値を設定してプローブすることもできます。

シリアル化の観点からは、フィールドをトランジェントに変更することは、フィールドを削除することと同じです。保存もロードもされません。ただし、以前は非一時的なフィールドを一時的であると宣言すると、serialVersionUID固定されていない場合は変更されます。

アイテムごとに serialVersionUID がハードコードされ、ファイル内の serialVersionUID一致する場合、質問に対する答えは次のとおりです。

  1. 何もない。
  2. 何もない。
  3. 何もない。

「何もない」とは、一時フィールド (存在する場合) に値を割り当てずにクラスが逆シリアル化され、エラーが報告されないことを意味します。

serialVersionUID が一致しない場合、残りのクラスが一致していても例外がスローされます。

于 2013-01-11T10:31:36.543 に答える