下面提到的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();
}
}
答案 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
答案 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