加深关于Serializable的理解

我们知道java.io.Serializable接口是将一个对序列化,所实现的效果就是可以将对象保存起来(例如:硬盘、网络等)。今天一道面试题出的很有意思,题目大概如下:

================Parent.java===================

package com.test;
import java.io.Serializable;
public class  Parent  {
public Parent(){
System.out.print("p");
}
}
=======================Sub.java===============================
 
public class Sub extends Parent implements Serializable{
public Sub(){
super();
System.out.print("c");
}
}
========================Test.java==============================
package com.test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test {
public static void main(String[] args) throws Exception {
String data = "E:\\test\\IO_0010\\src\\o.dat";
Sub sub = new Sub();
FileOutputStream fos = new FileOutputStream(data);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(sub);
oos.close();
fos.close();
FileInputStream fis = new FileInputStream(data);
ObjectInputStream ois = new ObjectInputStream(fis);
Sub s =(Sub)ois.readObject();
fis.close();
ois.close();
}
}

==========================结束================================

然后输出的结果是:

pcp

当时我选的答案是pcpc,当初我是这样理解的(没做过实验时)。

1、当实例化子类的时候,会先去调用父类的构造函数,所以输出的是p。

2、再去调用子类的构造函数,输出c。

3、读取对象的时候,首先取出父类对象的构造函数,这里又输出p。

4、然后去调用子类的构造函数,输出c

但是事实证明,这么想是有些问题的。于是我又写了个例子,做了个测试。

前2步的理解是基本是正确的。

由于Sub实现了Serialiable接口,对所以sub对象被保存到文件中去了,当使用ObjectInputStream.readObject() 去读取对象的时候。sub的构造函数就不再调用了,但是他的父类Parent没有时间任何接口,父类没有被保存。当读取Sub对象就会去重新构造父类。即调用父类的构造方法,所以输出了p,而没有再次调用子类的构造方法。

如果父类也实现的了Serializable接口,那么重新读取对象的时候就不会再去构造父类或者是子类了。默认,子类也会去继承父类实现的接口。

posted @ 2010-10-12 08:37  【小洲】  阅读(290)  评论(0编辑  收藏  举报