posts - 51, comments - 17, trackbacks - 0, articles - 9
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

当序列化遇到继承时……

Posted on 2007-03-09 22:44 chenweicai 阅读(451) 评论(0)  编辑  收藏

当序列化遇到继承…

当一个父类实现Serializable接口后,他的子类都将自动的实现序列化。

以下验证了这一点:
package InherSerialTest;

import java.io.Serializable;

public class SuperA implements Serializable {

 private int supervalue;

 public SuperA(int supervalue) {
  super();
  // TODO Auto-generated constructor stub
  this.supervalue = supervalue;
 }
 
 public int getSupervalue() {
  return supervalue;
 }

 public void setSupervalue(int supervalue) {
  this.supervalue = supervalue;
 }

 public String toString(){
  return "supervalue is :" + supervalue;
 }
}

package InherSerialTest;

public class SubB extends SuperA {

 private int subvalue;

 public SubB(int supervalue, int subvalue) {
  super(supervalue);
  // TODO Auto-generated constructor stub
  this.subvalue = subvalue;
 }

 public int getSubvalue() {
  return subvalue;
 }

 public void setSubvalue(int subvalue) {
  this.subvalue = subvalue;
 }

 public String toString() {
  // TODO Auto-generated method stub
  return super.toString() + " ,subvalue " + subvalue;
 }
 
}

package InherSerialTest;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class InherSerialTest {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub

  SubB sub = new SubB(100,200);
  
  try{
   ObjectOutputStream oos = new ObjectOutputStream(
     new FileOutputStream("c:\\InherSerialTest.txt"));
   oos.writeObject(sub);
   oos.close();
   
   ObjectInputStream ois = new ObjectInputStream(
     new FileInputStream("c:\\InherSerialTest.txt"));
   SubB sub2 = (SubB)ois.readObject();
   System.out.println(sub2);
   ois.close();
  }catch(Exception e){
   e.printStackTrace();
  }
 }

}


结果是:supervalue is :100 ,subvalue 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;

其二,子类要负责序列化(反序列化)父类的域。
如果我们将上列中的SuperA没有实现Serializable接口,而是在SubB类中实现Serializable接口的话,即:

public class SuperA  {}
public class SubB extends SuperA implements Serializable{}

我们再次运行时,将会产生错误:

java.io.InvalidClassException: InherSerialTest.SubB; no valid constructor
 at java.io.ObjectStreamClass.<init>(Unknown Source)
 at java.io.ObjectStreamClass.lookup(Unknown Source)
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.writeObject(Unknown Source)
 at InherSerialTest.InherSerialTest.main(InherSerialTest.java:21)

果真如docs中所说的一样,父类缺少无参构造函数是不行的。



接下来,按照docs中的建议我们改写这个例子:
package InherSerialTest2;

import java.io.Serializable;

public abstract class SuperC {

 int supervalue;

 public SuperC(int supervalue) {
  super();
  // TODO Auto-generated constructor stub
  this.supervalue = supervalue;
 }
 
// 父类没有实现Serializable接口,子类要可序列化的话,父类必须要有无参构造函数
 public SuperC(){
  
 }

 public int getSupervalue() {
  return supervalue;
 }

 public void setSupervalue(int supervalue) {
  this.supervalue = supervalue;
 }

 public String toString() {
  // TODO Auto-generated method stub
  return "supervalue : " + supervalue;
 }

}

package InherSerialTest2;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

import InherSerialTest.SuperA;

public class SubC extends SuperC implements Serializable{
 
 private int subvalue;

 public SubC(int supervalue, int subvalue) {
  super(supervalue);
  // TODO Auto-generated constructor stub
  this.subvalue = subvalue;
 }

 public int getSubvalue() {
  return subvalue;
 }

 public void setSubvalue(int subvalue) {
  this.subvalue = subvalue;
 }

 public String toString() {
  // TODO Auto-generated method stub
  return super.toString() + " ,subvalue :" + subvalue;
 }
 
 private void writeObject(java.io.ObjectOutputStream oos)throws IOException{
  
  //先序列化对象
  oos.defaultWriteObject();
  //在序列化父类的域
  oos.writeInt(supervalue);
 }
 
 private void readObject(ObjectInputStream ois)throws IOException, ClassNotFoundException{
  
  //先反序列化对象
  ois.defaultReadObject();
  //再反序列化父类的域
  supervalue = ois.readInt();
 }
}

测试成功!


只有注册用户登录后才能发表评论。


网站导航: