只有子类已实现Serializable
接口。
import java.io.*;
public class NewClass1{
private int i;
NewClass1(){
i=10;
}
int getVal() {
return i;
}
void setVal(int i) {
this.i=i;
}
}
class MyClass extends NewClass1 implements Serializable{
private String s;
private NewClass1 n;
MyClass(String s) {
this.s = s;
setVal(20);
}
public String toString() {
return s + " " + getVal();
}
public static void main(String args[]) {
MyClass m = new MyClass("Serial");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serial.txt"));
oos.writeObject(m); //writing current state
oos.flush();
oos.close();
System.out.print(m); // display current state object value
} catch (IOException e) {
System.out.print(e);
}
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("serial.txt"));
MyClass o = (MyClass) ois.readObject(); // reading saved object
ois.close();
System.out.print(o); // display saved object state
} catch (Exception e) {
System.out.print(e);
}
}
}
我注意到的一件事是,父类没有序列化。然后,为什么它没有抛出NotSerializableException
确实它正在显示以下
输出
Serial 20
Serial 10
此外,输出与Serialization
和De-serialization
不同。我只是知道,这是因为父类没有实现Serializable
。但是,如果有人解释我,在对象序列化和反序列化过程中会发生什么。它如何改变价值?我无法弄清楚,我也在我的程序中使用了评论。所以,如果我在任何时候都错了,请告诉我。
答案 0 :(得分:28)
在反序列化期间,非序列化类的字段将是 使用公共或受保护的无参数构造函数初始化 类。必须可以访问子类的无参数构造函数 序列化。将恢复可序列化子类的字段 来自溪流。
另外,如果被序列化的类不可序列化,则仅抛出序列化异常。有不可序列化的父母是好的(只要他们有一个非arg构造函数)。对象本身不是Serializable,一切都扩展了它。 上面的引用也解释了为什么你得到值字段的不同值 - 设置了父类的no-arg构造函数,它将value字段设置为10 - 该字段属于(不可序列化的)父类,因此其值不是写入/从流中读取。
答案 1 :(得分:3)
如果MyClass持有对非序列化类对象的引用,则在运行时将获得NotSerializable异常。要进行测试,请修改MyClass,使其保存对NewClass1对象的引用。如果再次运行,则会抛出异常。
反序列化实质上是创建可序列化类的实例并恢复其属性。在此过程中,不会调用可序列化类的构造函数。而是调用第一个非可序列化超类的no arg构造函数。
在你的情况下,NewClass1的no arg构造函数将10分配给它的实例变量i。因此,在反序列化期间,它打印10而不是20。
答案 2 :(得分:0)
我没有对它进行过测试,但如果序列化基类实例,你将获得NotSerializableException
。当您的类包含一些不是Serializable
的成员时,它们也是一样的。
表示如果您创建对象NewClass1 nc1 = new NewClass1();
并尝试序列化obj nc1,您将获得所需的异常。