作者:刘颖
试题:
import java.io.*;
public class Forest implements Serializable{
private Tree tree = new Tree();
public static void main(String[] args){
Forest f = new Forest();
try{
FileOutputStream fs = new FileOutputStream("Forest.Ser");
ObjectOutputStream os=new FileOutputStream(fs);
os.writeObject(f);
os.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
class Tree {
}
A.compilation fails
B.an exception is thrown at runtime
C.an instance of Forest is serialized
D.an instance of Forest and an instance of Tree are both serialized
这个题目的答案是什么呢,大家可以先来考虑一下.
很多人都已经发现,在java中,流的层次看起来是比较混乱的.为了SCJP,我们就来理清它.
我们看一下,在jdk的源码中,ObjectOutputStream和FileOutputStream这两个类的定义.现在,我先把这两个类的签名拿出来,大家先看一下.
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants{} public class FileOutputStream extends OutputStream{}
主要是看extends后面的内容噢,ObjectOutputStream和FileOutputStream这两个类,都继承自OutputStream这样一个抽象类.按照我们一般的习惯,如果把继承当做一棵树来看的话,那么ObjectOutputStream和FileOutputStream这两个类应该是兄弟关系.
再看例子中,ObjectOutputStream os=new FileOutputStream(fs);一个类的变量,是不能指向它的兄弟的对象的.
其实这里应该算是一个笔误.我们只要把ObjectOutputStream os=new FileOutputStream(fs);改成ObjectOutputStream os=new ObjectOutputStream(fs);把FileOUtputStream的对象做为参数,去实例化一个ObjectOutputStream的对象就可以了.
等一下,关键问题在后面,在JDK API文档中写的很明确,ObjectOutputStream只能将支持 java.io.Serializable 接口的对象写入流中。
那么我们定义的Tree这个类还没有实现java.io.Serializable接口呢.
所以,这个程序根本不能通过编译.答案应该是A.
将Tree这个类改为:class Tree implements Serializable{}
现在可以运行一下了,我们会找到一个Forest.Ser文件,打开后,你会发现里面是一段乱码,这是因为ObjectOutputStream自动将每个 serializable 对象的类编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。所以我们看到的都是乱码也不奇怪了,只要是ObjectInputStream能够识别就行了.
|