J2SE中的序列化详解(二)

发表于:2007-06-11来源:作者:点击数: 标签:
当一个父类实现Serializable接口后,他的子类都将自动的实现序列化。以下验证了这一点: package Serial; import Java .io.Serializable; public class SuperC implements Serializable {//父类实现了序列化 int supervalue; public SuperC(int supervalue) {
当一个父类实现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 Aclearcase/" target="_blank" >ccessible) 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,子类要先序列化自身,然后子类要负责序列化父类的域。

(责任编辑:铭铭)

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
...