为什么在反序列化过程中不调用默认构造函数? [英] Why default constructor is not called while deserialization process?

查看:260
本文介绍了为什么在反序列化过程中不调用默认构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

I get the object of TestClass after deserialization but TestClass default constructor is not called. As per my understanding there are two ways to create object i.e either with new operator or TestClass.class.newInstance(). Both calls the default constructor.

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

Looks like deserialization process creates the object not with about two methods thats why default constructor is not called. Question is how deserialization creates the object ?

另一点是,如果TestClass扩展BaseTestClass并且BaseTestClass没有实现序列化,则调用
BaseTestClass的构造函数但不是TestClass。为什么这样 ?我相信它背后会有一些合理的理由。
但我没有得到它?

Another point is if TestClass extends BaseTestClass and BaseTestClass does not implements serialization , constructor of BaseTestClass is called but not TestClass. Why so ? I am sure there will be some logical reason behind it. But i am not getting it?

推荐答案

值得一读 Java对象序列化规范:3 - 对象输入类,其中 readObject 方法详细描述并逐步说明。

It's worth reading Java Object Serialization Specification: 3 - Object Input Classes where readObject method is described in details along with step by step explanation.

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

An instance of the class is allocated. The instance and its handle are added to the set of known objects.

内容恢复得当:


  1. 对于可序列化的对象,运行第一个非可序列化超类型的no-arg构造函数


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

  • For serializable classes, the fields are initialized to the default value appropriate for its type.

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

Then the fields of each class are restored by calling class-specific readObject methods, or if these are not defined, by calling the defaultReadObject method.

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

Note that field initializers and constructors are not executed for serializable classes during deserialization.

在正常情况下,编写流的类的版本将与读取流的类相同。在这种情况下,流中对象的所有超类型都将匹配当前加载的类中的超类型。

In the normal case, the version of the class that wrote the stream will be the same as the class reading the stream. In this case, all of the supertypes of the object in the stream will match the supertypes in the currently-loaded class.

如果编写流的类的版本具有与加载的类不同的超类型,则 ObjectInputStream 必须更加小心恢复或初始化不同类的状态。

If the version of the class that wrote the stream had different supertypes than the loaded class, the ObjectInputStream must be more careful about restoring or initializing the state of the differing classes.

必须逐步执行这些类,将流中的可用数据与要还原的对象的类进行匹配。流中出现但未在对象中出现的类的数据将被丢弃。

It must step through the classes, matching the available data in the stream with the classes of the object being restored. Data for classes that occur in the stream, but do not occur in the object, is discarded.

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

For classes that occur in the object, but not in the stream, the class fields are set to default values by default serialization.

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

For externalizable objects, the no-arg constructor for the class is run and then the readExternal method is called to restore the contents of the object.






了解拳头点的示例代码对于可序列化对象,运行第一个非可序列化超类型的无参数构造函数。

示例代码;

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

这篇关于为什么在反序列化过程中不调用默认构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆