gpt4 book ai didi

java - 为什么在反序列化过程中不调用默认构造函数?

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:46:47 27 4
gpt4 key购买 nike

ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.ser"));
TestClass tc = (TestClass)is.readObject();

我在反序列化后得到了 TestClass 的对象,但没有调用 TestClass 默认构造函数。据我了解有两种创建对象的方法,即使用 new 运算符或 TestClass.class.newInstance()。两者都调用默认构造函数。

看起来反序列化过程创建对象时没有使用大约两种方法,这就是为什么不调用默认构造函数的原因。问题是反序列化如何创建对象?

另外一点是如果 TestClass 扩展了 BaseTestClass 而 BaseTestClass 没有实现序列化,调用 BaseTestClass 的构造函数但不调用 TestClass。为什么这样 ?我相信这背后会有一些合乎逻辑的原因。但是我不明白?

最佳答案

值得一读Java Object Serialization Specification: 3 - Object Input Classes其中详细描述了 readObject 方法以及逐步说明。

它是如何工作的?

类的一个实例被分配。实例及其句柄被添加到已知对象集中。

适当还原的内容:

  1. 对于可序列化对象,运行第一个不可序列化父类(super class)型的无参数构造函数

    • 对于可序列化类,字段被初始化为适合其类型的默认值。

    • 然后通过调用特定于类的 readObject 方法恢复每个类的字段,或者如果这些字段未定义,则通过调用 defaultReadObject 方法。

    • 请注意,在反序列化期间不会为可序列化类执行字段初始值设定项和构造函数

    • 在正常情况下,写入流的类的版本与读取流的类的版本相同。在这种情况下,流中对象的所有父类(super class)型都将与当前加载的类中的父类(super class)型相匹配。

    • 如果写入流的类的版本与加载的类有不同的父类(super class)型,ObjectInputStream 必须更加小心地恢复或初始化不同类的状态。

    • 它必须遍历类,将流中的可用数据与正在恢复的对象的类进行匹配。丢弃出现在流中但未出现在对象中的类的数据。

    • 对于出现在对象中但不出现在流中的类,通过默认序列化将类字段设置为默认值。

  2. 对于可外部化的对象,运行该类的无参数构造函数,然后调用 readExternal 方法来恢复对象的内容。


理解第一点的示例代码对于可序列化对象,运行第一个不可序列化父类(super class)型的无参数构造函数。

示例代码;

class TestClass1 {
public TestClass1() {
System.out.println("TestClass1");
}
}

class TestClass2 extends TestClass1 implements Serializable {
public TestClass2() {
System.out.println("TestClass2");
}
}

public static void main(String[] args) throws Exception {
System.out.println("Object construction via calling new keyword");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("resources/dummy.dat"));
out.writeObject(new TestClass2());

System.out.println("Object construction via readObject method");
ObjectInputStream is = new ObjectInputStream(new FileInputStream("resources/dummy.dat"));
TestClass2 tc = (TestClass2) is.readObject();
}

输出:

Object construction via calling new keyword
TestClass1
TestClass2

Object construction via readObject method
TestClass1

关于java - 为什么在反序列化过程中不调用默认构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24096059/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com