8

Javaでは、静的フィールドと一時フィールドはシリアル化されません。ただし、静的フィールドを初期化すると、生成されたserialVersionUIDが変更されることがわかりました。たとえばstatic int MYINT = 3;、serialVersionUIDを変更します。この例では、クラスのバージョンが異なれば初期値も異なるため、これは理にかなっています。初期化によってserialVersionUIDが変更されるのはなぜですか?たとえばstatic String MYSTRING = System.getProperty("foo");、serialVersionUIDも変更されます。

具体的には、メソッドで初期化するとserialVersionUIDが変更されるのはなぜですか。私が遭遇した問題は、システムプロパティ値(getProperty)で初期化された新しい静的フィールドを追加したことです。この変更により、リモート呼び出しでシリアル化例外が発生しました。

4

4 に答える 4

6

これに関する情報は、バグ 4365406serialVersionUIDを計算するためのアルゴリズムにあります。基本的に、staticメンバーの初期化を で変更するとSystem.getProperty()、コンパイラはクラスを参照する新しいstaticプロパティをクラスに導入しますSystem(Systemクラスは以前はクラスで参照されていなかったと思います)。コンパイラによって導入されたこのプロパティは非公開ではないため、serialVersionUID計算に参加します。

道徳:常に明示的に使用serialVersionUIDしてください。CPUサイクルと頭痛の種を節約できます:)

于 2008-09-03T21:46:04.563 に答える
2

自動 serialVersionUID は、クラスのメンバーに基づいて計算されます。これらは、Sun JDK の javap ツールを使用してクラス ファイルに対して表示できます。

質問で言及されている場合、追加/削除されるメンバーは静的初期化子です。これは、クラス ファイルでは ()V として表示されます。メソッドの内容は、javap -c を使用して逆アセンブルできます。System.getProperty("foo") の呼び出しと MYSTRING への割り当てを行うことができるはずです。ただし、文字列リテラル (または Java 言語仕様で定義されている任意のコンパイル時定数) を使用した代入は、クラス ファイルによって直接サポートされているため、静的初期化子は必要ありません。

J2SE 1.4 (use -source 1.4 -target 1.4) 以前を対象とするコードの一般的なケースは、ソース コード (MyClass.class) でクラス リテラルとして表示される古い Class インスタンスへの静的フィールドです。Class インスタンスは必要に応じて Class.forName で検索され、静的フィールドに格納されます。serialVersionUID を混乱させるのは、この静的フィールドです。J2SE 5.0 から、ldc オペコードのバリアントがクラス リテラルを直接サポートし、合成フィールドが不要になりました。繰り返しますが、これはすべて javap -c で表示できます。

于 2008-09-05T15:32:57.873 に答える
0

仕様を正しく読んだ場合serialVersionUID、静的フィールドの静的な値を変更しても、自動は変更されないはずです。仕様の第5.6章をご覧ください。

ただし、これについて少し考えてみると、から始めて、を持つオブジェクトをstatic int MYINT = 3シリアル化してから、クラスを逆シリアル化すると、同じオブジェクトを取り戻すことが期待されます。つまり、MYINT = 3。したがって、静的初期化を変更するとserialVersionUID、同じオブジェクトを再び取得できないため、が変更されることが予想されます。

とにかく、これをすべてのシリアル化可能なクラスに保持すると、serialVersionUID:を制御できます。

private static final long serialVersionUID = 7526472295622776147L;
于 2008-09-03T12:01:30.663 に答える
0

より明確になるように質問を更新しました。リテラルを使用した初期化によって変更される理由は理解できますが、serialVersionUID動的初期化によって変更される理由はわかりません。メソッドで初期化する場合、もちろん、値は常に異なる場合があります。

serialVersionUID安全な変更であることが確実な場合にのみ、クラスの後続のバージョンで を明示的に設定しても問題ありません。

于 2008-09-03T12:13:09.107 に答える