您可以在这里快速查找:


 
您的位置: 编程学习 > java教程 > 200511
文章分类

Java技术
2005: 03 04 05 06 07 08
09 10 11 12
2006: 01 02

Asp.net
2005: 07 08 09 10 11 12
2006: 01 02

VB编程
2006: 02

Asp编程
2005: 11 12
2006: 01 02

C++/VC
2005: 10 11 12
2006: 01 02

Delphi
2005: 12
2006: 01 02

其它

 本文章适合所有读者

谈谈J2SE中的序列化(二)

alikeboy

 

谈谈J2SE中的序列化(二)

作者:Favo yang

 favoyang@yahoo.com

 

当序列化遇到继承…

当一个父类实现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.<init>(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, 子类要先序列化自身,然后子类要负责序列化父类的域