クラスがEclipseでSerializableを実装する場合、2つのオプションがあります。デフォルトを追加するserialVersionUID(1L)
か、生成するかserialVersionUID(3567653491060394677L)
です。最初の方がクールだと思いますが、多くの場合、2番目のオプションを使用している人を見かけました。生成する理由はありますlong serialVersionUID
か?
0L
最初だけ使用するように聞こえます。
クラスがEclipseでSerializableを実装する場合、2つのオプションがあります。デフォルトを追加するserialVersionUID(1L)
か、生成するかserialVersionUID(3567653491060394677L)
です。最初の方がクールだと思いますが、多くの場合、2番目のオプションを使用している人を見かけました。生成する理由はありますlong serialVersionUID
か?
0L
最初だけ使用するように聞こえます。
回答:
私の知る限り、これは以前のリリースとの互換性のためだけのものです。これは、以前にserialVersionUIDの使用を怠り、互換性があるはずであるがシリアル化が機能しなくなる原因となる変更を加えた場合にのみ役立ちます。
詳細については、Java Serialization Specを参照してください。
シリアル化バージョンUIDの目的は、オブジェクトの有効なシリアル化を実行するために、クラスのさまざまなバージョンを追跡することです。
アイデアは、クラスの特定のバージョンに固有のIDを生成することです。このIDは、シリアル化されたオブジェクトの構造に影響を与える新しいフィールドなど、クラスに新しい詳細が追加されたときに変更されます。
常に同じIDを使用します。たとえば1L
、将来、クラス定義が変更されてシリアル化されたオブジェクトの構造が変更された場合、オブジェクトを逆シリアル化しようとしたときに問題が発生する可能性が高くなります。
IDを省略した場合、Javaはオブジェクトのフィールドに基づいて実際にIDを計算しますが、これはコストのかかるプロセスであるため、手動で提供するとパフォーマンスが向上します。
以下に、クラスのシリアル化とバージョン管理について説明する記事へのリンクをいくつか示します。
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
上記のコメントは、Javaオブジェクト直列化仕様バージョン6.0から撮影された
生成されたものの主な理由は、すでに永続化されたコピーを持つクラスの既存のバージョンと互換性を持たせることです。
の「長い」デフォルトは、Java Serialization SpecificationでserialVersionUID
定義されているデフォルト値であり、デフォルトのシリアル化動作から計算されます。
したがって、デフォルトのバージョン番号を追加すると、構造的に何も変更されていない限り、クラスは(デ)シリアル化を高速化しますが、クラスを変更する(フィールドを追加/削除する)場合は、シリアルナンバー。
既存のビットストリームと互換性がある必要がない場合は、1L
そこに配置し、何かが変更されたときに必要に応じてバージョンをインクリメントできます。つまり、変更されたクラスのデフォルトのシリアル化バージョンが、古いクラスのデフォルトバージョンと異なる場合です。
を実装するクラスを定義するたびに、serialVersionUIDを作成する必要がありますjava.io.Serializable
。そうでない場合は、自動的に作成されますが、これは悪いことです。自動生成されたserialVersionUIDはクラスのメソッドシグネチャに基づいているため、将来クラスを変更してメソッドを追加した場合(たとえば)、クラスの「古い」バージョンのデシリアライズは失敗します。起こり得ることは次のとおりです。
serialVersionUIDを指定しない場合、Javaはその場でそれを作成します。生成されたserialVersionUIDはその番号です。クラスを以前のシリアル化されたバージョンと実際に互換性がないように変更したものの、ハッシュを変更した場合は、生成された非常に大きな数のserialVersionUID(またはエラーメッセージからの「予期される」番号)を使用する必要があります。 。それ以外の場合、自分ですべてを追跡している場合は、0、1、2 ...のほうが適切です。
serialVersionUID(3567653491060394677L)を生成するのではなく、serialVersionUID(1L)を使用すると、何か言っていることになります。
バージョン番号が1であるこのクラスの互換性のないシリアル化されたバージョンを持つこのクラスに影響を与えるシステムがないことを100%確信していると言っています。
シリアル化されたバージョン履歴が不明であるという言い訳を考えることができれば、自信を持って言うのは難しいかもしれません。その生涯において、成功したクラスは多くの人々によって維持され、多くのプロジェクトに住み、多くのシステムに常駐します。
あなたはそれに苦しむことができます。または、負けることを期待して宝くじをすることもできます。バージョンを生成した場合、問題が発生する可能性はほとんどありません。「ねえ、まだ誰も1を使っていないと思う」と思ったら、オッズは小さいよりも大きいです。0と1はクールだと思うので、ヒット率が高くなります。
-
serialVersionUID(1L)を使用するのではなく、serialVersionUID(3567653491060394677L)を生成すると、何か言っていることになります。
このクラスの歴史上、他のバージョン番号が手動で作成または生成された可能性があると言っていて、Longsは大きな数をおかしくしているので気にしません。
どちらの方法でも、クラスが存在する、または存在する可能性のある全宇宙でクラスをシリアル化するときに使用されるバージョン番号の履歴を完全に知らない限り、チャンスをつかんでいます。1がAOKであることを100%確認する時間があれば、それを試してください。それで十分な場合は、先に進んでやみくもに数を生成してください。抽選に失敗するよりも、宝くじに当たる可能性が高くなります。もしそうなら、私に知らせて、私はあなたにビールを買います。
宝くじをプレイするこのすべての話で、serialVersionUIDがランダムに生成されるという印象をあなたに与えたかもしれません。実際、数値の範囲がLongのすべての可能な値に均等に分散されている限り、問題はありません。ただし、実際には次のように行われます。
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
これで得られる唯一の違いは、ランダムソースが必要ないことです。クラス自体の変更を使用して結果を変更しています。しかし、鳩の巣の原理によれば、それがうまくいかず、衝突を起こす可能性はまだあります。それは信じられないほど信じられないほどです。ビールを一杯飲んで頑張ってね。
ただし、クラスが1つのシステムと1つのコードベースにしか存在しない場合でも、手動で数値を増やすと衝突の可能性がゼロになると考えると、人間を理解できなくなります。:)
まあ、serialVersionUIDは、「静的フィールドはシリアル化されない」というルールの例外です。ObjectOutputStreamは、serialVersionUIDの値を出力ストリームに書き込むたびに書き込みます。ObjectInputStreamはそれを読み取り、ストリームから読み取られた値がクラスの現在のバージョンのserialVersionUID値と一致しない場合、InvalidClassExceptionをスローします。さらに、シリアル化されるクラスで正式に宣言されたserialVersionUIDがない場合、コンパイラーは、クラスで宣言されたフィールドに基づいて生成された値を使用して、それを自動的に追加します。
@David Schmittsの回答に追加するには、経験則として、私は常にデフォルトの1Lを使用します。戻っていくつかの変更を数回行うだけで済みましたが、変更を加えてデフォルトの番号を毎回1つずつ更新すると、そのことがわかっていました。
私の現在の会社では自動生成された番号が必要なので、慣例としてそれを使用しますが、デフォルトを使用します。何らかの理由でシリアル化されたクラスの構造を絶えず変更することになると思わない限り、私の慣習として、それが作業する慣習ではない場合は、デフォルトを使用します。
シリアル化バージョンUIDの目的は、オブジェクトの有効なシリアル化を実行するために、クラスのさまざまなバージョンを追跡することです。
アイデアは、クラスの特定のバージョンに固有のIDを生成することです。このIDは、シリアル化されたオブジェクトの構造に影響を与える新しいフィールドなど、クラスに新しい詳細が追加されたときに変更されます。
簡単な説明:
データをシリアル化していますか?
シリアライゼーションとは、基本的にはクラスデータをファイル/ストリームなどに書き込むことです。逆シリアル化とは、そのデータをクラスに読み込むことです。
生産に入るつもりですか?
重要でないデータや偽のデータを使って何かをテストしているだけなら、心配しないでください(直接シリアル化をテストしているのでない限り)。
これは最初のバージョンですか?
その場合は、serialVersionUID = 1Lを設定します。
これは2番目、3番目などの製品バージョンですか?
ここで、serialVersionUIDについて心配する必要があり、それを詳しく調べる必要があります。
基本的に、書き込み/読み取りが必要なクラスを更新するときにバージョンを正しく更新しないと、古いデータを読み取ろうとするとエラーが発生します。