Java:为什么不反序列化调用构造函数和什么是最好的解决方法?

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

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

Java 1.5 的Java序列化规范说:

对于可序列化的对象,运行第一个不可序列化的超类型的无参数构造函数。对于可序列化的类,这些字段被初始化为适合其类型的默认值。然后通过调用特定于类的readObject方法来恢复每个类的字段,或者通过调用defaultReadObject方法来定义这些方法,如果这些方法没有定义。请注意,在反序列化期间,字段初始值设定项和构造函数不会被执行用于可序列化的类。

但是,这意味着如果我们在类中放置一个静态变量(例如计数器变量),它将不会像以前那样更新:

class Foo {
    static int t;

    public Foo() {
        t++;
    }
}

public class Bar extends Foo implements Serializable {
    static int t;

    public Bar() {
        t++;
    }
}

在这种情况下,如果一个实例Bar是反序列化的,那么计数器Foo是正确的,而计数器Bar是一个一个的。

我想知道为什么反序列化不会调用构造函数?由于看起来速度会有所提高,但它可能会导致潜在的问题。编译器可以很容易地设计为产生一个“静态构造函数”,它只更新将被更新的静态变量,并且在加载类时不依赖外部信息。

另外,我想知道避免这种情况的最好方法是什么?我能想到的解决方案是用静态变量上的操作打包反序列化。

提问于
用户回答回答于

反序列化不会调用构造函数,因为它的目的是在对象序列化时表示对象的状态,运行构造函数代码可能会干扰该构造函数。

用户回答回答于

没有深入理解为什么不调用构造函数(没有默认构造函数的对象,例如应该是Serializable),解决缺省行为问题的标准方法是提供自己的readObject()或writeObject()实现为你的班级。

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

扫码关注云+社区