Java:为什么反序列化不会调用构造函数以及什么是最佳解决方法?

zw3*_*324 16 java inheritance constructor deserialization

Java 1.5 的Java序列化规范说:

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

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

class Foo {
    static int t;

    public Foo() {
        t++;
    }
}

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

    public Bar() {
        t++;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我想知道为什么反序列化不会调用构造函数?由于看起来虽然这会在速度上获得一点点,但它可能会导致潜在的问题.编译器可以很容易地设计为生成一个"静态构造函数",它只更新将要更新的静态变量,并且在加载类时不依赖于外部信息.

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

感谢提前输入!

Nat*_*hes 34

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


ant*_*oft 11

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

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
    in.defaultReadObject();
    t++;
}
Run Code Online (Sandbox Code Playgroud)