2

私は非常に単純なクラス階層を持っています:

public class DropdownOption<T> /* does NOT implement Serializable */ {
    private T value;
    private String label;

    public DropdownOption() {
        this (null, null);
    }

    public DropdownOption(T value, String label) {
        this.value = value;
        this.label = label; 
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}

/**
 * Convenience decorator
 */
public class LongIdDropdownOption extends DropdownOption<Long> 
    implements Serializable {

    private static final long serialVersionUID = -3920989081132516015L;

    public LongIdDropdownOption() {
        super();        
    }

    public LongIdDropdownOption(Long value, String label) {
        super(value, label);
    }

    public Long getId() {
        return getValue();
    }

    public void setId(Long id) {
        super.setValue(id);
    }
}

Serializableを実装する LongIdDropdownOption の新しいインスタンスを作成すると、それをシリアル化します。次に、すぐに逆シリアル化します。逆シリアル化されたオブジェクトの両方のフィールドが null に設定されます。

public void testSerialization() throws Exception {
    LongIdDropdownOption option = new LongIdDropdownOption(1L, "One");         

    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(buffer);
    os.writeObject(option);
    os.close();

    ObjectInputStream is = new ObjectInputStream(
        new ByteArrayInputStream(buffer.toByteArray()));
    LongIdDropdownOption result = (LongIdDropdownOption) is.readObject();
    is.close();

    assertNotNull(result);        
    assertEquals("One", result.getLabel()); /** Fails, label is null */
}

基本クラスに Serializable を実装すると、コードが正しく機能し始めます。私の質問は...なぜですか?

4

3 に答える 3

4

ここのJavaドキュメントから

クラスAがSerializableを実装していないが、サブクラスBがSerializableを実装している場合、Bがシリアル化されると、クラスAのフィールドはシリアル化されますか?

シリアル化可能なオブジェクトのフィールドのみが書き出され、復元されます。オブジェクトは、シリアル化できないスーパータイプのフィールドを初期化する引数なしのコンストラクターがある場合にのみ復元できます。サブクラスがスーパークラスの状態にアクセスできる場合は、writeObjectとreadObjectを実装して、その状態を保存および復元できます。

于 2010-12-02T04:20:04.530 に答える
4

ここで説明するように-http ://java.sun.com/developer/technicalArticles/ALT/serialization「readObjectとwriteObjectをオーバーライドする一般的な理由の1つは、それ自体がシリアル化できないスーパークラスのデータをシリアル化することです」。

サブクラス化されたインスタンスにあると思われる状態は、APIまたはリフレクションを経由しないため、シリアル化には実際には表示されません。シリアル化プロセスに関する限り、状態はSerializableを実装しないスーパークラスに属します。これはあなたがそれを失うところです。

これを説明するJavaオブジェクトシリアル化仕様へのリンクは次のとおりです。http: //download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html

于 2010-12-02T04:22:28.683 に答える
4

子クラスのみが実装するためSerializable、そのフィールドのみがJVMによってシリアル化されます。JVMは、リフレクションを使用してクラスのフィールドを一覧表示するため、親メンバーを子クラスのメンバーとは見なしません。

于 2010-12-02T04:14:14.580 に答える