Java对象序列化和继承

时间:2011-12-25 23:30:26

标签: 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;

public Bar(String name, int id) {
    super(name);
    this.id = id;
}
}

请注意,Foo没有实现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);

} 

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

3 个答案:

答案 0 :(得分:22)

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

但该课程必须遵守某些规则:

  

http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html

     

要允许序列化非序列化类的子类型,   子类型可能承担保存和恢复状态的责任   超类型的公共,受保护和(如果可访问)包   领域。只有在类中,子类型才可以承担此责任   它扩展了一个可访问的无参数构造函数来初始化   阶级的国家。如果这样,声明一个Serializable类是错误的   事实并非如此。

回答@Sleiman Jneidi的评论问题, 在上面提到的oracle文档中,它明确提到了

  

在反序列化期间,将使用类的public或protected no-arg构造函数初始化非可序列化类的字段。必须可以对可序列化的子类访问no-arg构造函数。可序列化子类的字段将从流中恢复。

因此,调用类Foo的默认no-arg构造函数导致初始化。

答案 1 :(得分:4)

可能是the defaultWriteObject can only write the non-static and non-transient fields of the current class。一旦超类没有实现Serializable接口,超类中的字段就无法序列化到流中。

答案 2 :(得分:0)

实际上当你要读取父类对象时,因为它根本没有序列化..所以对于非序列化的东西,JVM会经历与我们使用new关键字创建新对象时所用的相同的过程。 / p>