Java 1.5的Java serialization spec说:
对于可序列化对象,第一个是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++;
}
}
在这种情况下,如果Bar
的一个实例被反序列化,那么Foo
的计数器是正确的,Bar
的计数器是一个一个的。
我想知道为什么反序列化不会调用构造函数?由于看起来虽然这会在速度上获得一点点,但它可能会导致潜在的问题。编译器可以很容易地设计为生成一个“静态构造函数”,它只更新将要更新的静态变量,并且在加载类时不依赖于外部信息。
另外,我想知道避免这种情况的最佳方法是什么?我能想到的解决方案是使用静态变量上的操作打包反序列化。
感谢提前输入任何内容!
答案 0 :(得分:34)
反序列化不会调用构造函数,因为它的目的是在序列化时表示对象的状态,运行构造函数代码可能会干扰它。
答案 1 :(得分:11)
没有考虑为什么没有调用构造函数(没有默认构造函数的对象,例如,应该是Serializable)的哲学,解决默认行为问题的标准方法是提供自己的readObject()或writeObject ()你的类的实现。
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
in.defaultReadObject();
t++;
}