Serializable:自定义序列化

原创 2015年07月08日 13:49:24

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

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

相关文章推荐

winform 自定义序列化源码

  • 2009年11月26日 14:48
  • 19KB
  • 下载

IO Serializable 序列化和反序列化以及自定义的序列化

package IO; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOExcep...

Serializable序列化

  • 2014年04月27日 21:57
  • 26KB
  • 下载

通过自定义MVC的Controller的Json转换器解决日期序列化格式问题

今日,在MVC框架下使用EasyUI的datagrid加载数据时,服务端返回的Json日期格式为 /Date(1433088000000+0800)/ ,需要客户端进一步转换,而且也不符合EasyUI...
  • mole
  • mole
  • 2015年07月13日 11:02
  • 2114

hbasesink 自定义序列化类

  • 2017年09月14日 14:50
  • 69KB
  • 下载

(Swift) iOS Apps with REST APIs(四) -- 自定义Alamofire的响应序列化

本文将继续前面的教程,讲解如何将REST API获取JSON格式的数据转换为Swift对象。 重要说明: 这是一个系列教程,非本人原创,而是翻译国外的一个教程。本人也在学习Swift,看到这...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Serializable:自定义序列化
举报原因:
原因补充:

(最多只允许输入30个字)