关闭

Serializable:自定义序列化

标签: 自定义序列化
337人阅读 评论(0) 收藏 举报
分类:

序列化对象可以自定义序列化,也可以使用默认序列化
如何选择呢?
这就要从序列化的目的说起,序列化的目的简单来说就是保存,之后可以还原,这就是说只要我们能达到这个目的,都是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是更好的选择。

测试程序

@Test
public 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();
}

@Test
public 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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场