序列化

原创 2007年09月19日 14:45:00
 
Serializable
实现Serializable接口
       这是最简单的序列化方式。下面的例子将类的内容写到文件中,然后再反序列化声称新的对象。
public class MyClass implements Serializable
{
    private String name;
    private int value;
       
    public MyClass(String name,int value)
    {
        this.name=name;
        this.value=value;
    }
       
    public static void main(String[] args) throws ClassNotFoundException,IOException
    {
        MyClass c=new MyClass("freebird",8);
        ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("myclass.out"));
        out.writeObject(c);
       
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("myclass.out"));
        MyClass c2=(MyClass)in.readObject();
    }
}
       Serializable接口实际上只是一个标记接口,Java虚拟机利用Class对象帮助实现对象的序列化和反序列化功能。
       上面的例子我们使用了文件流,如果使用网络流对象,我们可以轻松的将对象在网络上传递。
       如果MyClass对象内部包含了复杂的树结构的成员,这种机制也可以工作的很好。
控制Serializable接口
       作为Serializable自动序列化的补充,我们可以将成员变量使用transient关键字修饰。这些变量将不会被序列化和反序列化。
Serializable接口的缺陷
       1)序列化格式将成为类的公有接口的一部分,如果类的设计发生改变,则通常序列化的格式也会发生改变,这样就等于该动了类的接口。因此有可能造成类的新旧版本的不兼容。
       2)Serializable接口的发序列化机制绕过了默认构造函数。通常我们使用构造函数是为了在对象创建时检查是否符合某些约束条件。Serializable接口的自动反序列化机制不会作到这点。
       3)性能不高
 
实现Externalizeable接口
       上面实现Serializable接口的方式会将所有的成员都序列化,但有时候并不需要将所有成员都序列化成字节流。我们可以让自己的类实现Externalizable接口。Externalizable接口扩展了Serializable接口,并且声明了下面两个抽象方法:
    void writeExternal(ObjectOutput out) throws IOException;
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
       我们需要实现这两个方法,并且还需要为我们的类提供公有默认构造函数。
public class MyClass implements Externalizable
{
    private String name;
    private int value;
   
    public MyClass()
    {
        name="hello";
        value=5;
    }
    public MyClass(String name,int value)
    {
        this.name=name;
        this.value=value;
    }
   
    public void writeExternal(ObjectOutput out) throws IOException
    {
        out.writeObject(name);
        out.writeInt(value);
    }
   
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {
        name=(String)in.readObject();
        value=in.readInt();
    }
       
    public static void main(String[] args) throws ClassNotFoundException,IOException
    {
        MyClass c=new MyClass("freebird",8);
        ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("myclass.out"));
        out.writeObject(c);
       
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("myclass.out"));
        MyClass c2=(MyClass)in.readObject();
    }
}
       这种方法比Java自动序列化机制性能更高。因为程序员只关心某些数据域的序列化,而Java自动化序列化机制必须了解类的全部结构。
 
 
非常规做法
       这是一种容易引起混乱的做法,并不推荐使用。这种做法就是只实现Serializable接口,不实现Externalizable接口,但是类自己必须提供下面的两个方法,访问权限为私有。
    void writeObject(ObjectOutputStream out) throws IOException;
    void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
       我们并不需要显示的调用这两个方法,Java保证由ObjectOutputStream.writeObject调用我们的writeObject,保证由ObjectInputStream.readObject调用我们的readObject方法。居然可以调用我们的私有方法,这种打破常规的做法当然不值得推荐。
 
从一个字节流中多次反序列化得到的对象是同一个对象
       因为Java为每个对象编了一个序号,序号和对象的内存位置对应。第一次反序列化的时候,会创建新对象,第二次就会根据序号进行查找,如果找到该对象,就不再创建,直接返回该对象的引用。
       因为有了序号,所以也不会多次重复序列化,特别是写到文件中时。
静态成员变量的序列化需要手动完成
 
序列化字节流格式
字符串对象的格式:74 2字节长度 字符串
字符串中的字符都是Unicode字符,采用modified UTF-8格式
类的描述信息格式
72
2字节长度
类名
8字节指纹 //根据类,父类,接口,域类型和方法签名计算出来的唯一数据
1字节标志
2字节的数据域描述符计数
数据域描述符//1字节类型码+2字节域名长度+域名+类名(如果域为对象)
78(结束标记)
超类(如果没有则为70)
 
对象格式:73+类描述信息+对象数据
 
详细请参考<<Core Java 2>> Volum I 12.5.2
关键是知道指纹的存在
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

序列化、反序列化到底是什么?

一、序列化、反序列化到底是什么? (1) 名词解释 对象的序列化 : 把Java对象转换为字节序列并存储至一个储存媒介的过程。 对象的反序列化:把字节序列恢复为Java对象的过程。 (2)...
  • Nicholas_Nick
  • Nicholas_Nick
  • 2016年03月30日 10:12
  • 3828

序列化和反序列化的简单理解

一、序列化和反序列化的概念   把对象转换为字节序列的过程称为对象的序列化。   把字节序列恢复为对象的过程称为对象的反序列化。   对象的序列化主要有两种用途:   1) 把对象的字节序列永久地保...
  • abc6368765
  • abc6368765
  • 2016年05月10日 19:24
  • 31217

Android中两种序列化方式的比较Serializable和Parcelable

Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用者两种序列化方式。还有,我们需要对象持久化到存储设备或者通过网络...
  • wangchunlei123
  • wangchunlei123
  • 2016年05月08日 13:33
  • 10315

二叉树的序列化和反序列化实现(C++)

题目: 实现二叉树的序列化和反序列化的函数。 思路:         二叉树的序列化 即给定二叉树的头指针,按照某种遍历方式将所有结点链接为一个数组或字符串(/指针)。        ...
  • u013575812
  • u013575812
  • 2015年12月05日 14:39
  • 1195

java,什么是序列化,怎么实现序列化

转自:http://zhidao.baidu.com/question/202556575.html?qbl=relate_question_0&word=%CA%B2%C3%B4%CA%C7java...
  • zhangzhangjava
  • zhangzhangjava
  • 2016年04月12日 17:33
  • 3208

Java序列化,反射,注解(一)

序列化: 什么是序列化,为什么要做序列化,考虑一种场景,考虑这种应用发生在要对一个对象做永久性保存的时候, 可以把它保存到电脑磁盘,也可以保存到数据库。而在你需要用到这个对象的时候可以从磁盘或数据库...
  • chaogu94
  • chaogu94
  • 2016年09月02日 17:43
  • 1179

google protobuf入门(序列化和反序列化)

ProtoBuf,全称是Protocol Buffers, 它是谷歌内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范。谷歌自己内部很多程序之间的通信协议都用了ProtoBuf。 下面介绍的是...
  • paul342
  • paul342
  • 2016年05月19日 17:09
  • 4678

Spring Data Redis提供的几种序列化的比较

* redis虽然提供了对list set hash等数据类型的支持,但是没有提供对POJO对象的支持,底层都是把对象序列化后再以字符串的方式存储的。* Spring data提供了若干个Seria...
  • CSDN_XueXiaoQiang
  • CSDN_XueXiaoQiang
  • 2017年06月23日 17:05
  • 1172

java中为什么要实现序列化,什么时候实现序列化?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络上传输。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是...
  • tlycherry
  • tlycherry
  • 2013年05月28日 22:19
  • 10468

Java中List或者HashMap对象-序列化和反序列化并附读写文件操作

关于常用的序列化工具可以看下文章 浅析若干Java序列化工具 闲言少叙,直接上代码。 Json格式的序列化和反序列化使用alibaba的Fastjson,Maven项目需要引用包 com....
  • lcanghai
  • lcanghai
  • 2017年04月06日 19:21
  • 4109
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:序列化
举报原因:
原因补充:

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