Serializable:自定义序列化

来源:互联网 发布:小米手机网络制式查询 编辑:程序博客网 时间:2024/05/19 13:14

序列化对象可以自定义序列化,也可以使用默认序列化
如何选择呢?
这就要从序列化的目的说起,序列化的目的简单来说就是保存,之后可以还原,这就是说只要我们能达到这个目的,都是ok的。如果都ok那么就可以选择更ok的形式。

看下面这个例子:
OddNum 这是一个极其没有道理的例子,只是为了说明问题

public class OddNum implements Serializable{    /**     *      */    private transient static final long serialVersionUID = 9030591748255175591L;    //默认序列化对static成员不进行序列化    //默认序列化对transient修饰的对象不进行序列化,反序列化时给默认值,对于这里的Integer来说就是null    private transient Integer[] is = new Integer[100];    public OddNum()    {        for(int i=0;i<is.length;i++)        {            is[i] = i*2+1;        }    }    private void writeObject(ObjectOutputStream out) throws IOException    {        out.defaultWriteObject();        out.writeInt(is.length);        System.out.println("");    }    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException    {        in.defaultReadObject();        int capacity = in.readInt();        is = new Integer[capacity];        for(int i=0;i<capacity;i++)        {            is[i] = i*2+1;        }    }    public Integer[] getIs() {        return is;    }}

使用默认序列化是ok的。
因为Integer[]的值仅仅与length有关,只要拿到length我们就可以还原原始的对象,所以选择仅仅序列化length也是可以达到目的,所以选择自定义序列化也是ok的。
现在就再这两种方式中哪一种比较好呢,你会选择将整个数组序列化,还是仅仅序列化一个int值,很显然选择自定义序列化只序列化length是更好的选择。

测试程序

@Testpublic void testOut00() throws FileNotFoundException, IOException{    OddNum o = new OddNum();    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\temp00.txt"));    out.writeObject(o);    out.flush();    out.close();}@Testpublic void testIn00() throws FileNotFoundException, IOException, ClassNotFoundException{    ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\temp00.txt"));    OddNum o = (OddNum)in.readObject();    in.close();    Integer[] is = o.getIs();    for(Integer temp : is)    {        System.out.print(temp+" ");    }}

解释一下readObject:

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{    in.defaultReadObject();    int capacity = in.readInt();    is = new Integer[capacity];    for(int i=0;i<capacity;i++)    {        is[i] = i*2+1;    }}

反序列化其实是重新构造了一个新的实例,可以将反序列化看做是一个以流为参数的构造函数。
这里的is就是反序列化时,生成的新的对象的成员。由于is被transient 修饰,in.defaultReadObject()执行完以后,它的值是null,所以这里需要is = new Integer[capacity]初始化一下,然后通过拿到的length赋值。这样就还原了序列化之前的对象。

从过去几个测试程序可以看出,序列化无论怎么实现,用法是完全一样的,之后就不再写测试程序了。

0 0
原创粉丝点击