反序列化对象在所有字段中都为null

时间:2010-07-21 11:58:15

标签: java serialization null

我编写了Container<T>类,用于将其T项备份到多个集合中 - 主要是List<T>,其他是带有从项目派生的数据的各种地图,主要用于优化搜索。

类看起来像这样:

class Container<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private final List<T> items = Lists.newArrayList();
    private final Map<...> map1 = Maps.newHashMap();
    private final Map<...> map2 = Maps.newHashMap();
}

标准序列化就像魅力一样,但不需要序列化地图。我尝试将地图设置为transient并以这种方式使用readObject()

class Container<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private final List<T> items = Lists.newArrayList();
    private transient Map<...> map1;
    private transient Map<...> map2;

    public Container() {
        initContainer();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        initContainer();
    }

    private void initContainer() {
        map1 = Maps.newHashMap();
        map2 = Maps.newHashMap();
        // prepare data in maps
        for (T item: items) {
            map1.put(...);
            map2.put(...);
        }
    }
}

ObjectOutputStream.writeObject()ObjectInputStream.readObject()的简单测试再次有效。但是当我将Container集成到实际应用程序中时,这个类被序列化并反序列化为其他复杂类的一部分(实际上是Wicket Page),会发生奇怪的事情。

我做了一些调试,这是我的发现:

  • {(1}}与(n)项的序列化已经完成
  • Container的反序列化已经完成
  • 每个Container项的反序列化仅被调用(n-1)次(通过计算对其T方法的调用)
  • readObject()中有containerInit()个正确(n)个项目,但其中一个(其中一个不称为反序列化)处于非常奇怪的状态 - 所有字段都有{ {1}}值 - 我的代码在这里抛出NPE

问题:

  • 反序列化后该奇怪对象的状态是什么(它存在但没有List<T>调用而且在所有字段中都为null)?
  • 也许没有完成对这个奇怪对象的反序列化,但我已经读过从null读取对象是阻塞的,所以我列表中的所有对象都必须处于正确的状态。或者我忽视了什么?
  • 是否有任何技术/工具/练习来捕捉这样的事情?

谢谢。

1 个答案:

答案 0 :(得分:0)

正如我在评论中所写,问题是在Container.readObject()期间触摸序列化集合中的项目。其中一些对象在这一刻具有空字段。当我推迟对Container的反向外部反序列化时,这些对象具有正确的字段值。

我的假设

让对象包含其他对象的字段集合。父母和孩子都可以序列化,也可以收集。在readObject()方法中的自定义父反序列化期间,不能完全访问子级,它们存在但反序列化不完整。只有在处理父反序列化后才需要访问子项。

这个假设对我有用,但我仍然不知道为什么。