|
|
| |
|
|
J2SE - J2SE中的序列化之继承
|
|
来源: 作者:jingjingde.net 发布时间:2008-07-27
|
|
当一个父类实现Serializable接口后,他的子类都将自动的实现序列化。
以下验证了这一点:
package Serial; import java.io.Serializable; public class SuperC implements Serializable {//父类实现了序列化 int supervalue; public SuperC(int supervalue) { this.supervalue = supervalue; } public String toString() { return "supervalue: "+supervalue; } }
public class SubC extends SuperC {//子类 int subvalue;
public SubC(int supervalue,int subvalue) { super(supervalue); this.subvalue=subvalue; }
public String toString() { return super.toString()+" sub: "+subvalue; } }
public class Test1 {
public static void main(String [] args){ SubC subc=new SubC(100,200); FileInputStream in=null; FileOutputStream out=null; ObjectInputStream oin=null; ObjectOutputStream oout=null; try { out = new FileOutputStream("Test1.txt");//子类序列化 oout = new ObjectOutputStream(out); oout.writeObject(subc); oout.close(); oout=null;
in = new FileInputStream("Test1.txt"); oin = new ObjectInputStream(in); SubC subc2=(SubC)oin.readObject();//子类反序列化 System.out.println(subc2); } catch (Exception ex){ ex.printStackTrace(); } finally{ …此处省略 } } }
运行结果如下:
supervalue: 100 sub: 200
可见子类成功的序列化/反序列化了。
怎管让子类实现序列化看起来是一件很简单的事情,但有的时候,往往我们不能够让父类实现Serializable接口,原因是有时候父类是抽象的(这并没有关系),并且父类不能够强制每个子类都拥有序列化的能力。换句话说父类设计的目的仅仅是为了被继承。
要为一个没有实现Serializable接口的父类,编写一个能够序列化的子类是一件很麻烦的事情。java docs中提到:
“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. The error will be detected at runtime. ”
也就是说,要为一个没有实现Serializable接口的父类,编写一个能够序列化的子类要做两件事情:
其一、父类要有一个无参的constructor;
其二、子类要负责序列化(反序列化)父类的域。
我们将SuperC的Serializable接口去掉,而给SubC加上Serializable接口。运行后产生错误:
java.lang.Error: Unresolved compilation problem: Serializable cannot be resolved or is not a valid superinterface at Serial.SubC.(SubC.java:15) at Serial.Test1.main(Test1.java:19) Exception in thread "main"
果真如docs中所说的一样,父类缺少无参构造函数是不行的。
接下来,按照docs中的建议我们改写这个例子:
public abstract class SuperC { int supervalue; public SuperC(int supervalue) { this.supervalue = supervalue; } public SuperC(){}//增加一个无参的constructor public String toString() { return "supervalue: "+supervalue; } }
public class SubC extends SuperC implements Serializable { int subvalue;
public SubC(int supervalue,int subvalue) { super(supervalue); this.subvalue=subvalue; }
public String toString() { return super.toString()+" sub: "+subvalue; }
private void writeObject(java.io.ObjectOutputStream out) throws IOException{ out.defaultWriteObject();//先序列化对象 out.writeInt(supervalue);//再序列化父类的域 } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ in.defaultReadObject();//先反序列化对象 supervalue=in.readInt();//再反序列化父类的域 } }
运行结果证明了这种方法是正确的。在此处我们用到了writeObject/ readObject方法,这对方法如果存在的话,序列化时就会被调用,以代替默认的行为(以后还要探讨,先了解这么多)。我们在序列化时,首先调用了ObjectOutputStream的defaultWriteObject,它使用默认的序列化行为,然后序列化父类的域;反序列化的时候也一样。
归纳一下:
目的 行为
为一个实现Serializable接口的父类,编写一个能够序列化的子类 子类将自动的实现序列化
为一个没有实现Serializable接口的父类,编写一个能够序列化的子类 1, 父类要有一个无参的constructor;2, 子类要先序列化自身,然后子类要负责序列化父类的域
|
| |
|
[ 收藏]
[ 推荐]
[ 评论(0条)]
[返回顶部] [打印本页]
[关闭窗口] |
|
|
| |
|
|
|
|