为什么我的对象没有正确反序列化?

发布于 2024-10-05 04:18:50 字数 1903 浏览 0 评论 0原文

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

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 的新实例时,它确实实现了可序列化;将其序列化;然后立即反序列化它——然后反序列化的对象将其两个字段设置为 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 */
}

当我使基类实现 Serialized 时,代码开始正常工作。我的问题是...为什么?

I have a pretty simple class hierarchy:

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

When I create a new instance of the LongIdDropdownOption, which does implement Serializable; serialize it; and then immediately deserialize it -- then the deserialized object has both of its fields set to 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 */
}

When I make the base class implement Serializable, the code starts working correctly. My question is... why ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

み格子的夏天 2024-10-12 04:18:50

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

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

以下是 Java 对象序列化规范的链接,应该对其进行解释:
http://download.oracle.com/javase/6 /docs/platform/serialization/spec/serialTOC.html

As described here - http://java.sun.com/developer/technicalArticles/ALT/serialization "one common reason to override readObject and writeObject is to serialize the data for a superclass that is not Serializable itself".

The state that you think you have in your subclassed instance isn't really visible to the serialization as its not going via your API or reflection. As far as serialization process is concerned the state belongs in the super class that does not implement Serializable. This is where you lose it.

Here's a link to a Java Object Serialization Specification that should explain it:
http://download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html

残月升风 2024-10-12 04:18:50

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

Because since only the child class implements Serializable, only its fields will be serialized by the JVM. The JVM does not see the parent members as members of the child class, as it uses reflection to list the class' fields.

橙幽之幻 2024-10-12 04:18:50

来自 Java 文档 此处

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

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

From Java Docs Here

If class A does not implement Serializable but a subclass B implements Serializable, will the fields of class A be serialized when B is serialized?

Only the fields of Serializable objects are written out and restored. The object may be restored only if it has a no-arg constructor that will initialize the fields of non-serializable supertypes. If the subclass has access to the state of the superclass it can implement writeObject and readObject to save and restore that state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文