最新IBM水货笔记本价格,详细点击进入

查看完整版本: J2SE中的序列化之继承

风舞残阳 2008-4-1 11:22

J2SE中的序列化之继承

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

  以下验证了这一点:

  packageSerial;
  importjava.io.Serializable;
  publicclassSuperCimplementsSerializable{//父类实现了序列化
  intsupervalue;
  publicSuperC(intsupervalue){
  this.supervalue=supervalue;
  }
  publicStringtoString(){
  return"supervalue:"+supervalue;
  }
  }

  publicclassSubCextendsSuperC{//子类
  intsubvalue;

  publicSubC(intsupervalue,intsubvalue){
  super(supervalue);
  this.subvalue=subvalue;
  }

  publicStringtoString(){
  returnsuper.toString()+"sub:"+subvalue;
  }
  }

  publicclass[wiki]Test[/wiki]1{

  publicstaticvoidmain(String[]args){
  SubCsubc=newSubC(100,200);
  FileInputStreamin=null;
  FileOutputStreamout=null;
  ObjectInputStreamoin=null;
  ObjectOutputStreamoout=null;
  try{
   out=newFileOutputStream("Test1.txt");//子类序列化
   oout=newObjectOutputStream(out);
   oout.writeObject(subc);
   oout.close();
   oout=null;

   in=newFileInputStream("Test1.txt");
   oin=newObjectInputStream(in);
   SubCsubc2=(SubC)oin.readObject();//子类反序列化
   System.out.println(subc2);
  }catch(Exceptionex){
   ex.printStackTrace();
  }finally{
  …此处省略
  }
  }
  }

  运行结果如下:

  supervalue:100sub:200

  可见子类成功的序列化/反序列化了。

  怎管让子类实现序列化看起来是一件很简单的事情,但有的时候,往往我们不能够让父类实现Serializable接口,原因是有时候父类是抽象的(这并没有关系),并且父类不能够强制每个子类都拥有序列化的能力。换句话说父类设计的目的仅仅是为了被继承。

  要为一个没有实现Serializable接口的父类,编写一个能够序列化的子类是一件很麻烦的事情。javadocs中提到:

  “Toallowsub[wiki]type[/wiki]sofnon-serializableclassestobeserialized,thesubtypemayassumeresponsibilityforsavingandrestoringthestateofthesupertype'spublic,protected,and(ifaccessible)packagefields.Thesubtypemayassumethisresponsibilityonlyiftheclassitextendshasanaccessibleno-argconstructortoinitializetheclass'sstate.ItisanerrortodeclareaclassSerializableifthisisnotthecase.Theerrorwillbedetectedatruntime.”

  也就是说,要为一个没有实现Serializable接口的父类,编写一个能够序列化的子类要做两件事情:

  其一、父类要有一个无参的constructor;

  其二、子类要负责序列化(反序列化)父类的域。

  我们将SuperC的Serializable接口去掉,而给SubC加上Serializable接口。运行后产生错误:

  java.lang.Error:Unresolvedcompilationproblem:
  Serializablecannotberesolvedorisnotavalidsuperinterface
  atSerial.SubC.(SubC.java:15)
  atSerial.Test1.main(Test1.java:19)
  Exceptioninthread"main"

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

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

  publicabstractclassSuperC{
  intsupervalue;
  publicSuperC(intsupervalue){
  this.supervalue=supervalue;
  }
  publicSuperC(){}//增加一个无参的constructor
  publicStringtoString(){
   return"supervalue:"+supervalue;
  }
  }

  publicclassSubCextendsSuperCimplementsSerializable{
  intsubvalue;

  publicSubC(intsupervalue,intsubvalue){
   super(supervalue);
   this.subvalue=subvalue;
  }

  publicStringtoString(){
   returnsuper.toString()+"sub:"+subvalue;
  }

  privatevoidwriteObject(java.io.ObjectOutputStreamout)
  throwsIOException{
   out.defaultWriteObject();//先序列化[wiki]对象[/wiki]
   out.writeInt(supervalue);//再序列化父类的域
  }
  privatevoidreadObject(java.io.ObjectInputStreamin)
  throwsIOException,ClassNotFoundException{
   in.defaultReadObject();//先反序列化对象
   supervalue=in.readInt();//再反序列化父类的域
  }
  }

  运行结果证明了这种方法是正确的。在此处我们用到了writeObject/readObject方法,这对方法如果存在的话,序列化时就会被调用,以代替默认的行为(以后还要探讨,先了解这么多)。我们在序列化时,首先调用了ObjectOutputStream的defaultWriteObject,它使用默认的序列化行为,然后序列化父类的域;反序列化的时候也一样。

  归纳一下:

  目的行为

  为一个实现Serializable接口的父类,编写一个能够序列化的子类子类将自动的实现序列化

  为一个没有实现Serializable接口的父类,编写一个能够序列化的子类1,父类要有一个无参的constructor;2,子类要先序列化自身,然后子类要负责序列化父类的域
页: [1]
查看完整版本: J2SE中的序列化之继承