当我运行给定代码时,我得到A B A作为输出。我不明白为什么它再次打印A.

时间:2013-09-28 12:07:15

标签: java serialization deserialization objectinputstream objectoutputstream

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

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();
    }

}

5 个答案:

答案 0 :(得分:4)

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

  

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

当你致电A B时会打印

new B()objin.readObject()首先调用A的ctor然后调用B. 然后A仅调用A的ctor并打印第二个{{1}}。

答案 1 :(得分:1)

扩展任何类时,它会在创建super class的对象时调用subclass的构造函数。

只是示例:object B创建然后它将首先调用 A1 的构造函数。 并且objin.readObject()只调用A的构造函数。

修改

  

每个非可序列化超类的no-arg构造函数将在反序列化对象时运行。但是,反序列化的对象?构造函数在反序列化时不会运行。

答案 2 :(得分:1)

在反序列化期间调用A的构造函数,因为A未实现Serializable。这个答案解释得很好:

Java: Why doesn't deserialization invoke constructor & what's the best workaround?

答案 3 :(得分:0)

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

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


现在为objin.readObject();

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

  • 对于可序列化对象,运行第一个非可序列化超类型(即A1)的无参数构造函数。 由于A1未实现Serializable,因此将调用construtor

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

因此输出A B A

doc

中提到了这一点

答案 4 :(得分:0)

ObjectInputStream的Java文档说,

  

读取对象类似于运行new的构造函数   宾语。为对象分配内存并初始化为零   (空值)。 为非序列化调用no-arg构造函数   类,然后恢复可序列化类的字段   从最接近的可序列化类开始的流   java.lang.object并使用对象最具体的类完成。

因此在创建B类实例时,

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

它打印A,B和

反序列化时

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

它打印A,因为类A是不可序列化的,并且docs表示为非可序列化的类调用No-arg构造函数。

因此,您将输出为A B A