4

下面提到的代码返回 A B A 作为输出,但我不明白为什么在 B 之后再次打印 A 的逻辑。

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

class B extends A1 implements Serializable {
    public B() {
        System.out.println("B");
    }

}

public class Test {

    public static void main(String... args) throws Exception {
        B b = new B();      // Object of class B
        ObjectOutputStream objout=new ObjectOutputStream(new FileOutputStream("t.txt"));
        objout.writeObject(b);

        ObjectInputStream objin=new ObjectInputStream(new FileInputStream("t.txt"));
        objin.readObject();
    }

}
4

5 回答 5

4

这解释了它, B 的 ctor 不再被调用,因为它是可序列化的。

读取对象类似于运行新对象的构造函数。为对象分配内存并初始化为零 (NULL)。为不可序列化的类调用无参数构造函数。

A B在您调用时打印new B(),它首先调用 A 的 ctor,然后是 B。然后objin.readObject()只调用 A 的 ctor 并打印第二个A

于 2013-09-28T12:18:41.400 回答
1

当您扩展任何类时,它将super class在创建对象时调用构造函数subclass

举个例子:object Bcreated then它将首先调用A1的构造函数。并且objin.readObject()只调用 A 的构造函数。

编辑:

当对象被反序列化时,每个不可序列化超类的无参数构造器都会运行。但是,反序列化的对象呢?反序列化时构造函数不会运行。

于 2013-09-28T12:13:09.660 回答
1

构造函数A在反序列化期间被调用,因为A没有实现Serializable. 这个答案很好地解释了它:

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

于 2013-09-28T12:20:20.597 回答
0

构造函数从基类调用到派生类。

因此,B b = new B();构造函数将按 A->B 的顺序调用,因此打印A B


现在为objin.readObject();

只有 A 的构造函数会被调用,而不是 B 的构造函数。这是因为

  • 对于可序列化对象,运行第一个不可序列化超类型(即A1)的无参数构造函数。由于A1, 没有实现 Serializable ,它的构造函数将被调用

  • 在反序列化期间不serializable为类(即)执行构造函数B因此 B 的构造函数没有被第二次调用

因此输出,A B A

这在文档中提到

于 2013-09-28T12:23:21.810 回答
0

ObjectInputStream的 Java 文档说,

读取对象类似于运行新对象的构造函数。为对象分配内存并初始化为零 (NULL)。为不可序列化的类调用无参数构造函数,然后 从流中恢复可序列化类的字段,从最接近 java.lang.object 的可序列化类开始,到对象最具体的类结束。

因此,在创建 B 类实例时,

B b = new B();  // prints A B

它打印 A , B 和

在反序列化时,

objin.readObject();  // prints A as per docs

它打印 A 因为类 A 是不可序列化的,并且文档说为不可序列化的类调用了 No-arg 构造函数。

所以你一起得到输出A B A

于 2013-09-28T13:24:24.810 回答