您的位置:首页 > 编程语言 > Java开发

java对象的序列化和反序列化

2016-03-29 14:56 369 查看
文章参考 /article/4676439.html

一、序列化和反序列化的概念

把对象转换为字节的过程称为对象的序列化。

把字节序列恢复为对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:

1)把对象的字节序列永久的保存到硬盘上,通常放置到一个文件中;

2)在网络上传输对象的字节序列。

例如:在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

  当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

二、JDK类库中的序列化API

java.io.ObjectOutputStream代表对象的输出流,他的writeObject(Object obj)方法可对参数制定的obj对轩昂进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream代表对象的输入流,他的readObject(Object obj)方法从一个源输入流中读取字节序列,再把他们反序列为一个对象,并将其返回。

java中只有实现了Serializable和Externalizable接口的对象才能被序列化。Externalizable接口集成Serizalizable接口。区别如下:

Serializable接口:

1)系统自带的类序列化方法,主要包括writeObject(Object obj)方法来序列化和readObject(Object obj)方法来进行反序列化。类的序列化包含对象的类型和数据域。

2)如果类中的那个数据域不应该被序列化,那么应该将他标记成transient类型。

Externalizable接口:

1)这个接口是java提供的用户自己进行对象的序列化方法,用户必须实现readExternal()和whiteExternal()方法。

2)实现这个接口后,对象序列化的全部职责有自己负责,包括父类的数据和自己的数据。一般情况下主要是用户自定义一种序列化方式,只有数据域,没有对象的类型等,方便处理。

三、类的初始化过程(serializable接口原理)

注意:

每个对象都被赋予一个序列号。

相同对象的重复出现将被存储为对这个对象序列号的引用。

1)当序列化一个对象的时候,首先看这个对象的类是否已经序列化到输出流中。如果没有,则首先将这个类序列化后输出,然后关于类会形成一个指纹(根据类,超类等信息生成,跟serialVersionUID有关,后面会讲到),以后遇到这个类的对象的时候,直接将这个指纹号写到对象中,也就是说类只会被序列化一遍。

2)接着,开始序列化队对象。对象序列化的时候也会有个序列号,如果这个对象被多次引用,则下一次出现的时候直接将这个序列号写到相应位置即可。

四、类的版本管理(serialVersionUID应用)

如果一个类序列化后保存到文件中后,这个类改变了,那么相应类的指纹也改变了。当进行对象的反序列化时候由于类指纹不相同,所以不能进行加载,这就是版本冲突。

解决:可以在所有实现了Serializable接口的类中增加serialVersionUID来进行版本管理,因为在生成指纹的时候如果有这个数据,则直接使用serialVersionUID。那么当该改变类的时候,不改变这个数据,他们的指纹应该是一样的,就可以进行版本兼容了。(不过如果改变前和改变后数据域不一样的化,就会出现问题)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: