S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

Serializableインターフェース

serialVersionUIDのことは意識していたが、スーパークラスに引数なしのコンストラクタが必要になる場合がある。
JavaAPIより

非直列化可能クラスのサブタイプを直列化可能にするため、サブタイプでは、スーパータイプの public フィールド、protected フィールド、および (アクセス可能であれば) package フィールドの状態を保存したり復元したりする責任を想定できます。ただし、サブタイプでこの責任を想定できるのは、それが拡張するクラスに、クラスの状態を初期化するためのアクセス可能な引数なしのコンストラクタがある場合だけです。コンストラクタがない場合は、Serializable クラスを宣言するとエラーになります。エラーは実行時に検出されます。


で、Bits of Java > 一番近い Unserializable スーパークラスにはデフォルトコンストラクタが必須

Object -> U -> S -> Foo

上の継承関係で U, S, Foo クラスのクラス宣言は

public class U
public class S extends U implements java.io.Serializable
public class Foo extends S

となっているとします。ここで Foo のインスタンスを直列化する際に実際に直列化が行われるフィールドは S と Foo のフィールドだけです。つまり最初に Serializable インターフェイスを実装したクラスとそのクラス以下のサブクラスのフィールドは直列化の対象になりますが最初に Serializable インターフェイスを実装したクラスのスーパークラス以上のクラスのフィールドは直列化されません。当然復元時には直列化時の値は失われています。

上の例の場合は復元はまず U の引数のないコンストラクタが実行されます。それから S, Foo の順で直列化されているフィールドの復元が行われます。復元時に S, Foo のコンストラクタが実行されることはありません。 U より上位のクラスのフィールドは直列化時の値は失われ、 U のデフォルトコンストラクタ実行後の値が復元時の値となります。

U より上位のクラスのフィールドは直列化時の値は失われ…
マジっすかw


もし、スーパークラスフレームワーク等で既定のクラスの場合には、
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
を実装することで、データが失われることを回避する必要があると思われる。