1

Java シリアライゼーションに問題があります。ファイル システムに永続化された 1 つのオブジェクトがあるとします。後期バージョンでのオブジェクト構造の変更に合わせて、ファイルの構造を更新するにはどうすればよいですか?

たとえば、オブジェクトを保存した場合

A{int a; String b} to file

そして、構造を次のように変更しA{int a; String b, char c}ました A の後のバージョンに従って、以前に保存されたファイルを変更する方法はありますか?

4

2 に答える 2

2

それが可能だ。次のバージョンは、以前のバージョンと下位互換性を持つようにする必要があります。これを行う方法は、Java シリアライゼーション仕様 ( http://docs.oracle.com/javase/1.3/docs/guide/serialization/spec/version.doc.html ) で説明されています。

ただし、この問題は、ネイティブ Java シリアライゼーションを使用してオブジェクトを長期間永続化することが、通常は悪い考えである理由の良い例です。特定の形式 (XML、JSON など) を使用していた場合は、ファイル自体を簡単に読み取って変換したり、シリアライザーの実装が異なる任意のバージョンのファイルを読み取ったりして、1 つのバージョンからより簡単に移行することができます。別の人に。

于 2012-04-30T10:42:29.770 に答える
1

はい (構造があまり変わらず、特定のルールに従っている限り)。ファイルに次のシリアル化された表現が含まれているとします。

class Foo
{
  int a;                        // value = 42
  String b;                     // value = "don't panic"
}

ただし、オブジェクトを変更Fooしたため、クラス定義は次のようになりました。

class Foo
{
   int a;
   String b;
   char c;
}

ファイルを読み込むと、シリアライゼーション メカニズムが自動的に のインスタンスFooを存在させ、a を 42 に、b を「パニックにならない」に設定します。の値cがストリームになかったので、デフォルトで、Java のデフォルト値 (この場合、char の場合は 0x0000) に設定されます。

これでオブジェクトができたので、次の値を設定できますc

foo.c = 'Z';

オブジェクトをシリアル化してファイルに書き込むと、ファイルには次のシリアル化された表現が含まれます。

class Foo
{
  int a;                        // value = 42
  String b;                     // value = "don't panic"
  char c;                       // value = 'Z'
}

上で見たようcに、オブジェクト ストリームで見つからなかったときにデフォルト値が与えられました。別のデフォルト値を定義したい場合があります。シリアライゼーション メカニズムは、シリアライズ/デシリアライズ時にカスタム コードを実行する方法を提供します。詳細については、SerializableのJavadoc を参照してください ( の説明を参照してくださいreadObject())。


編集: JB Nizet が指摘しているように、 と呼ばれる特別なシリアル化フィールドがありserialVersionUIDます。オブジェクトのバージョン ID がオブジェクト ストリームの内容と一致することを確認する必要があります。次のようにオブジェクトに明示的に設定できます。

private static final long serialVersionUID = 1L;

ただし、最初に指定しなかった場合は、フィールドとメソッド シグネチャのハッシュからアルゴリズム的に生成された値を使用して自動的に書き出されます。この番号を再生成する必要がある場合 (クラスで定数として定義できるようにするには、serialverツールを使用する必要があります。

于 2012-04-30T10:41:39.690 に答える