问题描述
假设你有这两个类,Foo 和 Bar,其中 Bar 扩展了 Foo 并实现了 Serializable
Say you have these two classes, Foo and Bar where Bar extends Foo and implements 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 被序列化时会发生什么?
Notice that Foo doesn't implement Serializable
. So what happens when bar is serialized?
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".问题是,当类没有序列化时,为什么会调用默认构造函数?
it prints "Default 21".The question is, why the default constructor get called when the class is not serialized?
推荐答案
Serializable 只是给定类的标记接口".
Serializable is just a "marker interface" for a given class.
但该类必须遵守某些规则:
But that class must adhere to certain rules:
http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html
为了允许不可序列化的类的子类型被序列化,子类型可能承担保存和恢复状态的责任超类型的公共、受保护和(如果可访问)包领域.只有当类它扩展了一个可访问的无参数构造函数来初始化班级的状态.如果这样,则声明类 Serializable 是错误的事实并非如此.
To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case.
回答@Sleiman Jneidi 在评论中提出的问题,在上面提到的oracle文档中,它明确提到
to answer @Sleiman Jneidi question asked in comment,in oracle documentation mentioned above, its clearly mentioned
在反序列化期间,不可序列化类的字段将使用类的公共或受保护的无参数构造函数进行初始化.可序列化的子类必须可以访问无参数构造函数.可序列化子类的字段将从流中恢复.
因此,调用的类 Foo 的默认无参数构造函数导致初始化.
Thus, default no-arg constructor of class Foo called of, resulted in initialization.
这篇关于Java对象序列化与继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!