Java 如何不序列化继承的非瞬态字段? 问题

Java 如何不序列化继承的非瞬态字段? 问题,java,serialization,Java,Serialization,我有一个可序列化的类(我们称之为a)和一个非瞬态布尔字段,以及一个子类(B),对于该子类,同一个字段应该是瞬态的。我该怎么做 更准确地说,我希望在反序列化B时将该字段还原为默认布尔值(false),尽管我希望在反序列化A时将其还原为正确的值。但从A继承的其他字段仍应还原 从功能上讲,A表示在会话之间恢复的对象,B是一种特定类型的A,其状态应在每个新会话上重置 快速代码示例: 公共类A实现java.io.Serializable{ 私有字符串标签; //非瞬态 私有布尔域; 公共字符串getLab

我有一个可序列化的类(我们称之为a)和一个非瞬态布尔字段,以及一个子类(B),对于该子类,同一个字段应该是瞬态的。我该怎么做

更准确地说,我希望在反序列化B时将该字段还原为默认布尔值(
false
),尽管我希望在反序列化A时将其还原为正确的值。但从A继承的其他字段仍应还原

从功能上讲,A表示在会话之间恢复的对象,B是一种特定类型的A,其状态应在每个新会话上重置

快速代码示例:

公共类A实现java.io.Serializable{ 私有字符串标签; //非瞬态 私有布尔域; 公共字符串getLabel(){ 退货标签; } 公共void setLabel(字符串标签){ this.label=标签; } 公共布尔值字段(){ 返回字段; } 公共无效设置字段(布尔字段){ this.field=字段; } } 公共类B扩展了A{ //此类的字段应该是暂时的 //标签应保持非暂时性 }
我选择不保留的一些可能的解决方案
  • 一个简单的解决方案是将
    B extends A
    更改为
    A extends B
    ,使字段暂时化,并将
    writeObject()
    添加到A以序列化字段。然而,
    B扩展了A
    的功能含义,我不认为将其还原是明智的

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

  • 我试图编写一个
    writeObject()
    方法来模拟一个瞬态字段,但它不起作用,我也说不出原因。如果有人有线索,那可能是我的解决方案:

公共类B扩展了{
私有void writeObject(ObjectOutputStream out)引发IOException{
//保存当前状态
布尔字段=isField();
//已同步以确保未询问此实例
//而更改为序列化
已同步(此){
//模拟瞬态并序列化
设置字段(假);
out.defaultWriteObject();
//恢复状态
设置字段(字段);
}
}
}
  • 编辑:@rocketboy使用阴影的解决方案很有效,但我不喜欢阴影,因为它会留下一个未使用的字段(A的非瞬态字段永远不会被使用,而B的瞬态版本将被写入和读取)。不过,这可能是一个解决方案。经过实验的Java开发人员是否认为这是一个干净的解决方案
公共类B扩展了{
//阴影A的场
私有瞬态布尔域;
@凌驾
公共布尔getField(){
返回字段;
}
@凌驾
公共无效设置字段(布尔字段){
this.field=字段;
}
}

答案 按照@m1o2的建议,我已经能够使用接口实现我的解决方案:

public类B扩展了实现java.io.Externalizable的{
//不要忘记有一个公共的无参数构造函数
//让序列化工作
公共图书馆B(){
}
@凌驾
public void writeExternal(ObjectOutput out)引发IOException{
//只写我感兴趣的领域
writeObject(getLabel());
}
@凌驾
public void readExternal(ObjectInput in)引发IOException,
ClassNotFoundException{
//按写入顺序读取序列化字段
setLabel(.readObject()中的字符串);
}
}

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

如果您不关心超类字段(所有字段)你可以使用界面

我想你当然可以在孩子的课堂上掩盖它。这不是违反了Liskov的替代原则吗?@rocketboy:是的,我可以很容易地做到。例如,如果我的领域受到保护。但我通常使用私有字段,子类必须像其他任何人一样使用he访问器@太空卡车司机:我不知道利斯科夫的替代原理。你问了一个很好的问题。快速阅读让我觉得Java的继承编码规则确保了这一原则得到尊重。我觉得还可以。我不更改对象的属性,我只希望在每次会话开始时重新设置它们(以这种方式编写后,
readObject()
解决方案感觉不那么糟糕…。@rocketboy我使用阴影添加了一个解决方案。我关心超类中的一些字段,但在这种情况下,Externalizable符合我的需要。我在问题的末尾加了一个例子。谢谢