java - 如何不序列化继承的非 transient 字段?

标签 java serialization

问题

我有一个带有非 transient boolean 字段的可序列化类(我们称它为 A),以及一个子类 (B),该类的同一字段应该是 transient 的。我该怎么做?

更准确地说,我希望在反序列化 B 时将字段恢复为默认 boolean 值 (false),尽管我希望在反序列化 A 时将其恢复为正确的值。其他字段尽管如此,还是应该恢复从 A 继承的。

在功能上,A 代表一个在 session 之间恢复的对象,B 是 A 的特定类型,其状态应在每个新 session 上重置。

快速代码示例:

public class A implements java.io.Serializable {

    private String label;
    // non-transient
    private boolean field;

    public String getLabel() {
        return label;
    }

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

    public boolean isField() {
        return field;
    }

    public void setField(boolean field) {
        this.field = field;
    }
}

public class B extends A {
    // field should be transient for this class
    // label should remain non-transient
}

我选择不保留的一些可能的解决方案

  • 一个简单的解决方案是将 B extends A 更改为 A extends B,使字段成为 transient ,并添加一个 writeObject() 到 A 以序列化该字段。但是,B extends A 具有功能意义,我不认为恢复它是明智的。

  • 我可以实现一个 readObject() 方法来覆盖该字段的反序列化值。然而,这感觉像是一个肮脏的解决方案,除非没有其他选择,否则我不希望使用它。

  • 我尝试编写一个 writeObject() 方法来模拟 transient 场,但它不起作用,我也不知道为什么。如果有人有线索,那可能是我的解决方案:

public class B extends A {
    private void writeObject(ObjectOutputStream out) throws IOException {
        // save current state
        boolean field = isField();

        // synchronized to make sure this instance is not interrogated
        // while changed for serialization
        synchronized (this) {
            // emulate transient state and serialize
            setField(false);
            out.defaultWriteObject();

            // restore state
            setField(field);
        }
    }
}
  • 编辑:@rocketboy 使用阴影的解决方案有效,但我对阴影感到不舒服,因为它会留下一个未使用的字段(永远不会使用 A 的非 transient 字段,而 B 的 transient 版本将被写入和读取)。虽然这可能是一个解决方案。经验丰富的 Java 开发人员是否认为这是一个干净的解决方案?
public class B extends A {
    // shadow A's field
    private transient boolean field;

    @Override
    public boolean getField() {
        return field;
    }

    @Override
    public void setField(boolean field) {
        this.field = field;
    }
}

答案

按照@m1o2 的建议,我已经能够使用Externalizable 实现我的解决方案了。接口(interface):

public class B extends A implements java.io.Externalizable {

    // Do not forget to have a public no-arg constructor
    // for Serialization to work
    public B() {
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // Write only the fields I am interested in
        out.writeObject(getLabel());
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        // Read the serialized fields IN THE ORDER THEY WERE WRITTEN
        setLabel((String) in.readObject());
    }
}

但是请注意,这是适用的,因为 A 和 B 是简单类。对于具有许多字段且有发展趋势的类,这可能会花费更多(除非使用一些基于反射的代码)。

最佳答案

如果您不关心父类(super class)字段(所有),您可以使用 Externalizable界面

关于java - 如何不序列化继承的非 transient 字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17941654/

相关文章:

java - LibGDX android在屏幕中生成随机位置

java - 无法写入连接到 URLConnection 的 BufferedOutputStream

java.io.NotSerializedException : com. sun.faces.context.FacesContextImpl weblogic

php - 从jquery序列化函数发送值获取php数组

Django 反序列化 - 我已经指定了一个自然 key 管理器,但它不会反序列化

java - 列名称中包含 "é"的 iSeries JDBC Sql 语句抛出 java.sql.SQLException : [SQL0104]

java - 在 GWT 中从 JsArray<JavaScriptObject> 转换为 List<JSONObject>

java - 不同设备上的游戏速度不一样

c++ - 从 Armadillo boost 序列化稀疏矩阵

c# - 我是否需要反序列化来自 DocumentDb 的查询结果?