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

具有不可序列化部分的Java序列化,java,serialization,Java,Serialization,我有: 在MyClass2中,是一个不可序列化的属性。如何序列化和反序列化此对象 更正:MyClass2当然不是一个接口,而是一个类。MyClass2只是一个接口,所以技术上它没有属性,只有方法。也就是说,如果实例变量本身不可序列化,我所知道的唯一解决方法就是声明这些字段为瞬态 例: 当您声明一个字段时,在序列化和反序列化过程中将忽略它。请记住,当您使用瞬态字段反序列化对象时,该字段的值将始终是默认值,通常为null 注意:您还可以重写类的readResolve方法,以便根据其他系统状态初始化临

我有:

在MyClass2中,是一个不可序列化的属性。如何序列化和反序列化此对象


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

MyClass2只是一个接口,所以技术上它没有属性,只有方法。也就是说,如果实例变量本身不可序列化,我所知道的唯一解决方法就是声明这些字段为瞬态

例:

当您声明一个字段时,在序列化和反序列化过程中将忽略它。请记住,当您使用瞬态字段反序列化对象时,该字段的值将始终是默认值,通常为null


注意:您还可以重写类的readResolve方法,以便根据其他系统状态初始化临时字段。

您需要实现writeObject和readObject,并手动序列化/反序列化这些字段。有关详细信息,请参阅java.io.Serializable的javadoc页面。Josh Bloch的高效Java也有一些关于实现健壮和安全序列化的好章节。

您可以从查看transient关键字开始,该关键字将字段标记为对象持久状态的一部分。

如果您可以修改MyClass2,解决此问题的最简单方法是声明属性transient。

是一个伟大的库,用于对任何对象进行快速Java到XML序列化,无论其是否可序列化。即使XML目标格式不适合您,您也可以使用源代码来学习如何使用它。

取决于MyClass2的成员不可序列化的原因

如果有一些很好的理由说明MyClass2不能以序列化的形式表示,那么很可能同样的理由也适用于MyClass,因为它是一个子类

通过实现readObject和writeObject,可以为MyClass编写自定义序列化表单,这样MyClass中MyClass2实例数据的状态就可以从序列化数据中适当地重新创建。如果MyClass2的API是固定的,并且您不能添加Serializable,那么这就是解决方法


但首先,您应该弄清楚为什么MyClass2不可序列化,并可能对其进行更改。

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

该章中与您的问题相关的几点:

假设您想序列化MyClass2中不可序列化字段的状态,MyClass必须可以直接或通过getter和setter访问该字段。MyClass必须通过提供readObject和writeObject方法来实现自定义序列化。 不可序列化字段的类必须具有API,以允许获取其状态以写入对象流,然后在以后从对象流读取时使用该状态实例化新实例。 根据有效Java的第74项,MyClass2必须有一个MyClass可以访问的无参数构造函数,否则MyClass不可能扩展MyClass2并实现可序列化。 我在下面写了一个简单的例子来说明这一点

private transient Foo foo;

串行代理是序列化不可序列化类或至少子类的实例的一种有用方法。实际上,实现writeReplace返回完全不同的可序列化类的实例,该类实现readResolve返回原始对象的副本。我在

上写了一个序列化java.awt.BasicStroke的示例,弹出了几种可能性,我在这里继续:

按照建议实现writeObject和readObject 声明属性transient,它将不会像 如所述使用XStream 使用由所述的串行代理
如果可能,可以将不可串行的部件设置为瞬态


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;
  }
}
否则您可以使用。Kryo是一个快速高效的Java对象图序列化框架,例如Java.awt.Color的Java序列化需要170个字节,Kryo只需要4个字节,它还可以序列化不可序列化的对象。Kryo还可以执行自动深度和浅层复制/克隆。这是从对象到对象的直接复制,而不是对象->字节->对象

下面是一个如何使用kryo的示例

private transient SomeClass myClz;
还可以通过注册精确的序列化程序来压缩序列化对象:

Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();

你能不能修改MyClass2?不可序列化的属性值是否需要通过序列化保留?正确的方法取决于此。MyClass2可以修改。但是,最好不要这样做,因为我是在它上面构建的,它可以被其他人修改。这并不能回答这个问题-问题说明MyClass2包含不可序列化的属性,理想情况下,MyClass2不应该被修改。你是对的,我回答这个问题时没有仔细阅读。我修改了答案。哦,我希望得到某种注释,比如@NonSerialization:-/hi,你能解释一下怎么做吗
要将XStream与不可序列化的对象一起使用?文档非常简单,本教程从未实现可序列化的类开始,并向您展示如何序列化它们:
Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));