M S*_*ach 3 java serialization
ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.ser"));
TestClass tc = (TestClass)is.readObject();
Run Code Online (Sandbox Code Playgroud)
我在反序列化后得到了TestClass的对象,但是没有调用TestClass的默认构造函数.根据我的理解,有两种方法可以创建对象,即使用new运算符或TestClass.class.newInstance().两者都调用默认构造函数.
看起来像反序列化过程创建对象不是用两个方法,这就是为什么不调用默认构造函数.问题是反序列化如何创建对象?
另一点是,如果TestClass扩展BaseTestClass并且BaseTestClass没有实现序列化,则调用BaseTestClass的构造函数但不调用TestClass.为什么这样 ?我相信它背后会有一些合理的理由.但我没有得到它?
值得一读的是Java对象序列化规范:3 - 对象输入类,其中readObject详细描述了方法以及逐步说明.
分配了一个类的实例.实例及其句柄将添加到已知对象集中.
内容适当恢复:
对于可序列化对象,运行第一个非可序列化超类型的no-arg构造函数.
对于可序列化的类,字段将初始化为适合其类型的默认值.
然后通过调用特定于类的readObject方法来恢复每个类的字段,或者如果未定义这些方法,则通过调用该defaultReadObject方法来恢复.
请注意,在反序列化期间,不会对可序列化类执行字段初始值设定项和构造函数.
在正常情况下,编写流的类的版本将与读取流的类相同.在这种情况下,流中对象的所有超类型都将匹配当前加载的类中的超类型.
如果编写流的类的版本具有与加载的类不同的超类型,则ObjectInputStream必须更加小心地恢复或初始化不同类的状态.
它必须逐步执行这些类,将流中的可用数据与要还原的对象的类进行匹配.流中出现但未在对象中出现的类的数据将被丢弃.
对于在对象中但不在流中出现的类,默认序列化将类字段设置为默认值.
对于可外部化的对象,运行该类的no-arg构造函数,然后readExternal调用该方法以恢复该对象的内容.
用于理解第一点的示例代码对于可序列化对象,运行第一个非可序列化超类型的无参数构造函数.
示例代码;
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();
}
Run Code Online (Sandbox Code Playgroud)
输出:
Object construction via calling new keyword
TestClass1
TestClass2
Object construction via readObject method
TestClass1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2634 次 |
| 最近记录: |