BがAを拡張し、AがSerializableを実装している場合、「BimplementsSerializable」と書く必要がありますか?
いいえと思いますが、確認をお願いします...
また、シリアル化IDをAに入れると... Bにも入れる必要がありますか? Aのシリアル化IDを保護する必要がありますか(プライベートではありません)?
はい。サブクラスを明示的にシリアル化可能としてマークする必要はありません。
また、idをprotected
としてマークすると、(コンパイラーの観点から)機能します。
ただし、グッドプラクティスとして、すべてのクラスに独自のプライベートserialVersionUID
が必要です。
派生をSerializableとして明示的にマークする必要はなく、継承されます。ただし、親からのserialVersionUIDは継承されますが、シリアル化プロセスでは使用されません。子にserialVersionUIDを追加しない場合、子が生成されます。
下記参照:
public class A implements Serializable {
protected static final long serialVersionUID = 1L;
}
public class B extends A {
}
public class Main {
public static void main(String[] args){
A a = new A();
B b = new B();
Class aClass = a.getClass();
Class bClass = b.getClass();
long aUid = ObjectStreamClass.lookup(aClass).getSerialVersionUID();
long bUid = ObjectStreamClass.lookup(bClass).getSerialVersionUID();
System.out.printf("serialVersionUID:\n");
System.out.printf("b inherited from a: %d\n", b.serialVersionUID);
System.out.printf("a used by serialization: %d\n",aUid);
System.out.printf("b used by serialization: %d\n",bUid);
}
}
出力:
serialVersionUID:
aから継承されたb:1
シリアル化で使用される:1
bシリアル化で使用:-3675232183873847366
コンパイラの観点からは、idを保護済みとしてマークするだけで十分です。ただし、理論的には、serialVersionUID
クラスのSerializable
フィールドのポイントは、クラスを逆シリアル化するときにクラスの「バージョン」を簡単に区別することです。つまり、特定のオブジェクトをいつ逆シリアル化できるかを明確に示すことです。提供されたクラスのインスタンスに(serialVersionUID
sが異なる場合、例外がスローされます)。オブジェクトのバージョンと性質を明確に追跡できるようにする場合は、各サブクラスでserialVersionUID
を宣言します。
@azodiousの回答への私の同意では、子クラスは親クラスのシリアル化可能なプロパティを継承しますが、serialVersionUIDを明示的に宣言する必要があります。
From Java docs: https://docs.Oracle.com/javase/8/docs/api/Java/io/Serializable.html
また、明示的なserialVersionUID宣言では、可能な場合はプライベート修飾子を使用することを強くお勧めします。このような宣言は、すぐに宣言するクラスにのみ適用されるためです。serialVersionUIDフィールドは、継承されたメンバーとしては役立ちません。
いいえ、Bはすでに基本クラスAを介して実装しているためです。これが、継承のすべてです。
Javaオブジェクトは、そのクラスまたはそのスーパークラスのいずれかがJava.io.SerializableインターフェイスまたはそのサブインターフェイスJava.io.Externalizableのいずれかを実装している場合にシリアル化可能です。
公式ドキュメントを見て、ここで見つけることができます: https://docs.Oracle.com/javase/tutorial/jndi/objects/serial.html