假设你有这两个类,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”。 问题是,为什么在未对类进行序列化时调用默认构造函数?
答案 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>