Java对象序列化和继承

Java对象序列化和继承,java,inheritance,serialization,object-serialization,Java,Inheritance,Serialization,Object Serialization,假设您有两个类,Foo和Bar,其中Bar扩展了Foo并实现了Serializable class Foo { public String name; public Foo() { this.name = "Default"; } public Foo(String name) { this.name = name; } } class Bar extends Foo implements java.io.Serializable { public int id; p

假设您有两个类,Foo和Bar,其中Bar扩展了Foo并实现了
Serializable

class Foo {

public String name;

public Foo() {
    this.name = "Default";
}

public Foo(String name) {
    this.name = name;
}
}

class Bar extends Foo implements java.io.Serializable {

public int id;

public Bar(String name, int id) {
    super(name);
    this.id = id;
}
}
请注意,Foo没有实现
Serializable
。那个么,当bar被序列化时会发生什么呢

    public static void main(String[] args) throws Exception {

    FileOutputStream fStream=new FileOutputStream("objects.dat");
    ObjectOutputStream oStream=new ObjectOutputStream(fStream);
    Bar bar=new Bar("myName",21);
    oStream.writeObject(bar);

    FileInputStream ifstream = new FileInputStream("objects.dat");
    ObjectInputStream istream = new ObjectInputStream(ifstream);
    Bar bar1 = (Bar) istream.readObject();
    System.out.println(bar1.name + "   " + bar1.id);

} 
它打印“默认21”。 问题是,为什么在类未序列化时调用默认构造函数?

Serializable只是给定类的“标记接口”

    public static void main(String[] args) throws Exception {

    FileOutputStream fStream=new FileOutputStream("objects.dat");
    ObjectOutputStream oStream=new ObjectOutputStream(fStream);
    Bar bar=new Bar("myName",21);
    oStream.writeObject(bar);

    FileInputStream ifstream = new FileInputStream("objects.dat");
    ObjectInputStream istream = new ObjectInputStream(ifstream);
    Bar bar1 = (Bar) istream.readObject();
    System.out.println(bar1.name + "   " + bar1.id);

} 
但该类必须遵守某些规则:

要允许序列化不可序列化类的子类型,请 子类型可能负责保存和恢复状态 超类型的公共、受保护和(如果可访问)包的 领域。只有当类 它有一个可访问的无参数构造函数来初始化 阶级的状态。如果出现以下情况,则声明类可序列化是错误的 事实并非如此

回答@Sleiman Jneidi在评论中提出的问题, 在上面提到的oracle文档中,其

在反序列化过程中,不可序列化类的字段将使用该类的public或protected no arg构造函数进行初始化。无参数构造函数必须可被可序列化的子类访问。可序列化子类的字段将从流中恢复


因此,类Foo的默认无参数构造函数调用of,导致初始化。

可能是这样。一旦超类没有实现Serializable接口,超类中的字段就不能序列化到流中。

实际上,当您读回父类对象时,因为它根本没有序列化。。因此,对于非序列化的东西,JVM将经历与使用new关键字创建新对象时相同的过程。

我知道这一点。但为什么它调用默认构造函数。我不是在问什么是可序列化的?@sleimanjneidi,因为“为了允许非序列化类的子类型被序列化,子类型可能负责保存和恢复超类型的公共、受保护和(如果可访问)包字段的状态”。这意味着
Bar
应该手动设置
Foo
name
字段,因为
Foo
是不可序列化的。如果不调用其构造函数,就不能突然创建无辜类的实例,因此串行规范要求调用不可序列化类的构造函数您可能需要一个串行代理。是的,如果超类未实现Serializable,它将不会被序列化,因此在反序列化时,将调用其默认构造函数,并将默认值分配给其所有变量。