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);
    }
}

当我创建一个 LongIdDropdownOption 的新实例时,它确实实现了 Serializable;序列化它;然后立即反序列化它——然后反序列化对象的两个字段都设置为空:

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

因为由于只有子类实现Serializable,JVM 只会序列化它的字段。JVM 不会将父成员视为子类的成员,因为它使用反射来列出类的字段。

于 2010-12-02T04:14:14.580 回答
4

从这里的 Java 文档

如果A类没有实现Serializable,而B的子类实现了Serializable,那么在B序列化的时候,A类的字段会被序列化吗?

只有 Serializable 对象的字段被写出和恢复。仅当对象具有将初始化不可序列化超类型的字段的无参数构造函数时,才能恢复该对象。如果子类可以访问超类的状态,它可以实现 writeObject 和 readObject 来保存和恢复该状态。

于 2010-12-02T04:20:04.530 回答
4

如此处所述 - http://java.sun.com/developer/technicalArticles/ALT/serialization “覆盖 readObject 和 writeObject 的一个常见原因是序列化本身不可序列化的超类的数据”。

您认为您在子类实例中的状态对于序列化并不真正可见,因为它没有通过您的 API 或反射进行。就序列化过程而言,状态属于不实现 Serializable 的超类。这就是你失去它的地方。

这是一个指向应该解释它的 Java 对象序列化规范的链接:http: //download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html

于 2010-12-02T04:22:28.683 回答