带有不可序列化部分的Java序列化

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

我有:

class MyClass extends MyClass2 implements Serializable {
  //...
}

在MyClass2中是一个不可序列化的属性。我怎样才能序列化(和反序列化)这个对象?

更正:MyClass2当然不是一个接口,而是一个类。

提问于
用户回答回答于

正如其他人指出的,Josh Bloch的Effective Java第11章是Java序列化不可或缺的资源。

有关你的问题的那一章有几点意味着:

  • 假设您想序列化MyClass2中的不可序列化字段的状态,那么该字段必须可以直接或通过getter和setter访问MyClass。MyClass必须通过提供readObject和writeObject方法来实现自定义序列化。
  • 非序列化字段的类必须有一个API来允许获取它的状态(用于写入对象流),然后用该状态实例化一个新实例(当从对象流中读取时)。
  • 根据Effective Java的第74项,MyClass2 必须具有MyClass可访问的无参数构造函数,否则MyClass不可能扩展MyClass2并实现Serializable。

我在下面写了一个快速示例来说明这一点。


class MyClass extends MyClass2 implements Serializable{

  public MyClass(int quantity) {
    setNonSerializableProperty(new NonSerializableClass(quantity));
  }

  private void writeObject(java.io.ObjectOutputStream out)
  throws IOException{
    // note, here we don't need out.defaultWriteObject(); because
    // MyClass has no other state to serialize
    out.writeInt(super.getNonSerializableProperty().getQuantity());
  }

  private void readObject(java.io.ObjectInputStream in)
  throws IOException {
    // note, here we don't need in.defaultReadObject();
    // because MyClass has no other state to deserialize
    super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
  }
}

/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {

  /* this property must be gettable/settable by MyClass.  It cannot be final, therefore. */
  private NonSerializableClass nonSerializableProperty;

  public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
    this.nonSerializableProperty = nonSerializableProperty;
  }

  public NonSerializableClass getNonSerializableProperty() {
    return nonSerializableProperty;
  }
}

class NonSerializableClass{

  private final int quantity;

  public NonSerializableClass(int quantity){
    this.quantity = quantity;
  }

  public int getQuantity() {
    return quantity;
  }
}
用户回答回答于

MyClass2只是一个界面,所以它没有任何属性,只有方法。这就是说,如果你有实例变量本身不可序列化,我知道解决它的唯一方法是声明这些字段是瞬态的。

例如:

private transient Foo foo;

当你声明一个场瞬态时,它将在序列化和反序列化过程中被忽略。请记住,当您使用瞬态字段反序列化对象时,该字段的值始终为缺省值(通常为空)。

请注意,您也可以重写类的readResolve()方法,以基于其他系统状态初始化瞬态字段。

扫码关注云+社区