簡體   English   中英

我怎么能不序列化繼承的非瞬態字段?

[英]How can I not serialize an inherited non-transient field?

這個問題

我有一個Serializable類(讓我們稱之為A),帶有一個非瞬態布爾字段,以及一個子類(B),同一個字段應該是瞬態的。 我怎樣才能做到這一點?

更確切地說,我希望在反序列化B時將字段恢復為默認的布爾值( false ),盡管我希望在反序列化時將其恢復為正確的值。但是,從A繼承的其他字段仍應恢復。

在功能上,A表示在會話之間恢復的對象,B是特定類型的A,其狀態應在每個新會話上重置。

快速代碼示例:

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 AA extends B ,使字段瞬態,並向A添加writeObject()以序列化字段。 但是, B extends A具有功能意義,我不相信將其恢復是明智的。

  • 我可以實現一個readObject()方法,它將覆蓋該字段的反序列化值。 然而,這感覺就像一個骯臟的解決方案,我不希望使用它,除非沒有其他選擇。

  • 我試着編寫一個writeObject()方法來模擬瞬態字段,但它不起作用,我不知道為什么。 如果有人有線索,那可能是我的解決方案:

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的非瞬態字段永遠不會被使用,而B的瞬態版本將被寫入和讀取)。 這可能是一個解決方案。 做實驗的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接口實現我的解決方案:

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是簡單的類。 對於具有許多字段且趨勢發展的類,這可能會花費更多(除非使用基於反射的一些代碼)。

如果您不關心Superclass字段(所有這些字段),您可以使用Externalizable接口

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM