2008-09-03 9 views
7

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

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

答えて

5

あなたはbug 4365406中とalgorithm for computing serialVersionUIDでそのことについていくつかの情報を見つけることができます。基本的には、でメンバーstaticの初期化を変更すると、Systemクラスを参照するクラスに新しいstaticプロパティが導入されています(このクラスは以前はクラス内でSystemクラスが参照されていなかったと仮定しています)非公開ではなく、serialVersionUID計算に参加します。

道徳:常にあなたには、いくつかのCPUサイクルといくつかの頭痛の種を保存します、明示的なserialVersionUIDを使用:)自動のserialVersionUIDは、クラスのメンバーに基づいて算出され

0

私が正しく仕様を読めばあなたは過渡フィールドの静的の値を変更した場合、自動serialVersionUIDは変更しないでください。仕様のChapter 5.6を見てください。

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

とにかく、すべての直列化可能クラスでこれを維持し、あなたがserialVersionUIDを制御することができます。

private static final long serialVersionUID = 7526472295622776147L; 
0

私はより明確にする質問を更新しました。なぜリテラルの初期化でserialVersionUIDが変更されるのですが、なぜ動的初期化によってそれが変更されるのか理解できません。メソッドで初期化する場合、値は常に異なる場合があります。 serialVersionUIDを設定

は、明示的にそれが安全な変化であることが確実な場合にのみ、クラスの以降のバージョンで結構です。

2

。これらは、Sun JDKのjavapツールを使用してクラスファイル用に表示できます。質問で述べた場合

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

J2SE 1.4(-source 1.4 -target 1.4を使用)以前のコードターゲティングは、ソースコード(MyClass.class)のクラスリテラルとして表示される古いClassインスタンスに対する静的フィールドです。 ClassインスタンスはClass.forNameで要求に応じて検索され、静的フィールドに格納されます。このstaticフィールドは、serialVersionUIDを中断します。 J2SE 5.0から、ldcオペコードの変種はクラスリテラルを直接サポートし、合成フィールドの必要性を排除します。やはり、これはすべてjavap -cで見ることができます。

関連する問題