为什么我的对象不能正确反序列化?

时间:2010-12-02 04:04:09

标签: java serialization serializable deserialization

我有一个非常简单的类层次结构:

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;序列化;然后立即反序列化它 - 然后反序列化的对象将其两个字段都设置为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时,代码开始正常工作。我的问题是......为什么?

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

来自Java Docs Here

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

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

答案 2 :(得分:4)

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

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

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