Java Exceptionクラスが拡張する基本クラスを変更した場合、serialVersionUID値を更新する必要がありますか?
-
07-07-2019 - |
質問
次のJava例外クラスを検討してください:
public class BarException extends RuntimeException {
// [...]
}
public class FooException extends BarException {
private static final long serialVersionUID = -5322002268075295537L;
// [...]
}
FooException
が RuntimeException
から直接派生するように、継承階層を更新して BarException
を削除する場合、これを変更する必要がありますか serialVersionUID
値?
// FooException with updated inheritance hierarchy
public class FooException extends RuntimeException {
private static final long serialVersionUID = ???;
// [...]
}
解決 3
仕様が混乱と議論を引き起こすほど不明確であり、明確な答えが出ていないことを考えると、経験的証拠を信頼することが唯一の選択肢です。
上記の質問から、 RuntimeException
から派生した BarException
から派生した FooException
の例を取得し、次に BarException コード>継承チェーンから、さまざまな組み合わせでシリアライゼーションとデシリアライゼーションを試すためのサンプルアプリケーションを作成しました。
次の結果が得られます。
serialVersionUID
を変更しない限り、元の FooException
を更新された FooException
として正常にシリアライズおよびデシリアライズできます。 および逆も同様です。
次の注意事項が適用されます。
- JDK 1.5.0_07を使用していますが、他のバージョンではこれを試していません。
-
FooException
には、タイプint
およびException
のメンバーがあり、正常にデシリアライズされています。 -
BarException
は、RuntimeException
に追加のメンバーを追加しません。
他のヒント
はい。 "階層を上下に移動すること" に従って、以前のシリアル化されたインスタンスとの非互換性が発生します。シリアル化仕様。
Java 1.5シリアル化仕様は、継承階層からクラスを削除することは互換性のある変更であるため、 serialVersionUID
を変更する必要はないことを示唆しています。
新しい FooException
( RuntimeException
から直接派生)に逆シリアル化する場合、 BarException
に関連するシリアル化ストリームの追加情報は無視されます。 )。
技術的には可能ですが、システムがシリアル化されたオブジェクトを保持するかどうか、および新しいリファクタリングされたコードのデプロイ方法を制御するかどうかによって異なります。
永続化を行わず、新しいバージョンのコードで展開全体を更新する場合、 serialVersionUID
を変更する必要はありません。