【问题标题】:Java partial (de)serialization of objects对象的Java部分(反)序列化
【发布时间】:2012-11-30 17:49:56
【问题描述】:

假设我们有 3 个类:

class foo { // not a singleton
    String s;
}
class bar {
    foo f;
    int i;
}
class baz {
    foo sameF;
}

现在我们创建实例

foo onlyFoo = new foo("the only one");
bar theBar = new bar(onlyFoo, 123);
baz theBaz = new baz(onlyFoo);

之后,我们希望将它们序列化存储在一个文件中。 如果我们反序列化 theBaz,修改 onlyFoo 并再次反序列化 theBaz 到文件,theBar 仍然包含原来的 onlyFoo,所以 onlyFoo 有两个不同的版本。

我想要的是我只存储 theBaz 和 theBar 没有 Foo,分别存储三个对象,一旦有人反序列化 theBaz 我也想只给他Foo。如果他再次反序列化更改后的 onlyFoo,theBaz theBar 将具有相同的修改后的 onlyFoo,因此如果有人请求一个对象(例如 theBar),他将获得带有所有引用对象的完整序列化对象(onlyFoo)就像正常的序列化过程会返回一样。

我知道我必须手动单独存储对象并保留引用,因为默认序列化无法处理此问题。 我不知道如何部分序列化/反序列化 Java 对象?我需要将原语及其包装器与“更高”对象分开并单独存储这些对象。

更新

  1. 我无法修改类。
  2. 我不知道所有的课程。它应该适用于我可能从未听说过的所有可序列化对象(它们可能是最终的也可能不是最终的

【问题讨论】:

  • 课程是否开放扩展?我的意思是它是最终的还是不是?
  • 更新了问题:“我不知道所有课程。它应该适用于我可能从未听说过的所有可序列化对象。我明白了,如果他们是最终的,那也可能是个大问题
  • 请考虑接受(复选标记)其中一位abswers

标签: java serialization deserialization binary-serialization


【解决方案1】:

如果你想要更多的控制,你可以覆盖 writeObject() 和 readObject() 并序列化自己。

class bar {
    ...

    private void writeObject(ObjectOutputStream stream) throws IOException {
      // let version 1, later when you need to have versioning. 
      stream.writeInt(version);
      stream.writeInt(i);
      // leave out 
      // stream.writeObject(foo);

    }
}
// read object the analog, see 

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/output.html#861

【讨论】:

  • 嗯,我不能修改类本身,但我可以将它们包装成代理。这个代理会以某种方式覆盖 writeObject,即它们序列化它们为之创建的对象而不是它们自己。然后我只是序列化代理。他们需要为此使用反射,但我看到的问题是它应该适用于所有可序列化的对象,即使我从未听说过它们。
  • 我将此标记为正确答案,因为它对我帮助很大。我正在创建一个工作原型,完成后我会在此处发布/链接它。
【解决方案2】:

用瞬态关键字标记你不想序列化的引用。

【讨论】:

  • 你说得对,但我无法更改 foo、bar 或 baz 的定义。这个想法是它适用于所有可序列化的对象。
  • 您必须手动将引用设置为 null。如果您想要通用解决方案,可以使用 java.reflection
  • 嗯,如果我得到另一个指向该对象的指针并将该字段设置为空,我可以稍后反序列化第一个对象并在反序列化第一个对象后将第二个对象设置为该字段。谢谢这应该工作。还有另一种选择吗?我希望我的方法的调用者也可以获得完整的序列化对象,并且我不想在反序列化后直接序列化它以存档它。
【解决方案3】:

您可以将foo transient 设为如下。

class bar {
    transient foo f;
    int i;
}

【讨论】:

  • 正确,但正如另一条评论中提到的,我无法修改这些类。
猜你喜欢
  • 2017-08-15
  • 1970-01-01
  • 2021-12-08
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多