25

新しいクラスに serialVersionUID を明示的に指定するのは良くないように思えます。レイアウトを変更する必要がある場合に変更しない場合と、変更する必要がない場合に変更する場合の 2 つのケースを考えてみましょう。

変更すべきときに変更されないのは、ほとんど明示的である場合に限られます。この場合、非常に微妙で見つけにくいバグが発生します。特に開発中は、クラスのレイアウトが頻繁に変更されます。ただし、明示的に指定されていない場合は変更され、逆シリアル化が大声で中断されます。ほとんどの場合、リポジトリをパージすることで解決されます。

変更すべきではない場合に変更するのは、暗黙的である場合に限られます。これは、クラス レイアウトが変更されたまれなケースですが、古いシリアル化された BLOB から逆シリアル化したい場合です。これは QA ( 5.2 から 5.2.1 へのアップグレード後の奇妙なエラー、添付のスタック トレースを参照)中にキャッチされる可能性があり、明示的な値を設定することで簡単に修正できます。

コメント?

4

6 に答える 6

21

クラス レイアウトの変更以外の理由で発生しない場合があります。問題は、コンパイラの実装に依存することです。Eclipse でデバッグを行い、javac で本番ビルドを行う場合 2 つの互換性のないデータ セットが作成される可能性があります。

于 2009-01-07T10:05:49.827 に答える
5

私の職場では、serialVersionUID の指定を明示的に禁止しています。これは、まさにあなたが提起した問題のためです。

さらに、保持するクラスは、内部にロジックを持たないデータを格納するためにのみ使用されるため、変更される唯一の方法は、データ メンバーの変更によるものです。

于 2009-01-07T12:19:58.450 に答える
4

ジョン・スキートが言ったことをさらに強調し、コメントと矛盾する:

「それが必要ない場合 (つまり、常に同じクラス バージョンでシリアル化および逆シリアル化する場合)、明示的な宣言を安全にスキップできます」

長期的にシリアル化せず、同じクラス バージョンを使用している場合でも、問題が発生する可能性があります。クライアント/サーバー コードを作成していて、クライアント コードがサーバーとは異なる jvm バージョン/実装で実行できる場合、互換性のない serialversionuid で同じ問題が発生する可能性があります。

要約すると、 serialversionuids を指定しないことが「安全」な唯一の場合は、長期的にシリアライズを行っておらず、シリアライズされたデータのすべてのコンシューマーが元のプロデューサーと同じ jvm 実装とバージョンを使用することが保証されている場合です。

要するに、 serialversionuid を使用しないことは、一般に、より有害な状況です。

于 2009-01-07T15:26:34.780 に答える
2

シリアライゼーションによる長時間の永続性をサポートする必要がある場合、ほとんどの場合、これをサポートするためにカスタム コードを使用する必要があり、明示的に を設定する必要がありserialVersionUIDます。そうしないと、古いシリアライズされたバージョンが新しいコードでデシリアライズできなくなるためです。

これらのシナリオでは、クラスが変更されたときにすべてのケースを正しく取得するために、すでに十分な注意が必要であるため、serialVersionUID は問題が最も少ないものです。

それが必要ない場合 (つまり、常に同じクラス バージョンでシリアライズおよびデシリアライズする場合)、計算された値によって正しいバージョンが使用されることが保証されるため、明示的な宣言を安全にスキップできます。

于 2009-01-07T10:06:21.650 に答える
1

やるかやらないかにserialVersionUID関わらず (私はそうすることをお勧めします)、シリアル互換性のための包括的なテスト セットを作成することを検討する必要があります。

シリアル形式を慎重に設計することも価値があります。これは実質的にパブリック API です。

于 2009-01-07T12:13:53.047 に答える
1

クライアントとサーバーのクラスとjvmが同じであるEJBの呼び出しなど、リモートメソッド呼び出しにシリアライゼーションを使用している場合は、これが最も一般的な使用法であると思われます。次に、serialVersionUIDを明示的に設定しますserialVersionUID が固定されているため、互換性のないクラス インスタンスが互換性があるものとして扱われる、説明のつかないバグが時折発生するという形で、重大な苦痛を引き起こす可能性があります。リモート呼び出しは、低レベルのシリアライゼーション中に静かに失敗し、オブジェクトの状態が一貫していない場合にのみ問題が発生します。クライアントとサーバーのクラスが何らかの形で異なることに気付いた場合にのみ、問題の原因を見つけることができます (ただし、serialVersionUID はもちろん異なります)。私の経験では、この理由で serialVersionUID を設定すると、良いことよりも害が大きくなります。

一方、serialVersionUID を明示的に古いデータを読み込むように設定すると、定義上、互換性のないバージョンを読み込むことになり、最終的にオブジェクトが矛盾した状態または不完全な状態になる可能性があります。この場合、serialVersionUID を設定すると、別の問題を回避できます。

于 2012-01-16T15:20:01.933 に答える