【问题标题】:When I run the given code I get A B A as output. I don't understand why it prints A again当我运行给定的代码时,我得到 A B A 作为输出。我不明白为什么它再次打印 A
【发布时间】:2013-10-04 16:42:30
【问题描述】:

下面提到的代码返回 一种 乙 一种 作为输出,但我不明白为什么在 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();
    }

}

【问题讨论】:

标签: java serialization deserialization objectinputstream objectoutputstream


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢!。我验证并理解了逻辑。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    举例:object B 被创建,那么它会首先调用 A1 的构造函数。 而objin.readObject() 只调用 A 的构造函数。

    编辑:

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

    【讨论】:

    • 不回答问题
    • @upog 是的,它没有像 OP 预期的那样回答。我编辑了答案。它可能对 OP 有所帮助。
    【解决方案4】:

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

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


    现在objin.readObject();

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

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

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

    因此输出,A B A

    doc中提到了这个

    【讨论】:

      【解决方案5】:

      ObjectInputStream 的 Java 文档说,

      读取一个对象类似于运行一个新对象的构造函数 目的。为对象分配内存并初始化为零 (空值)。 为不可序列化调用无参数构造函数 类,然后恢复可序列化类的字段 从最接近的可序列化类开始的流 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的输出

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-27
        • 2014-03-29
        相关资源
        最近更新 更多