2010-12-02 84 views
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的新实例;序列化它;然后立即反序列化 - 那么反序列化对象既有其字段设置为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

如此处所述 - 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

4

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

+0

谢谢,爱德华多,这是有道理的(在某种程度上)。这是否意味着基本上没有办法生成一个子类Serializable,而且还没有创建所有的父类Serializable呢?或者,这仍然有可能通过在子类中提供readObject和writeObject的自定义实现? – Bugmaster 2010-12-02 04:17:33

3

从Java文档Here

如果类A没有实现Serializable但是子类B实现Serializable接口,将A类的字段时,B的序列被序列化?

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

相关问题