java 序列化与反序列化

什么是序列化

(1)序列化是将对象转变为字节序列的过程,反序列化则是将字节序列恢复为对象的过程。

(2)对象序列化保存的是对象的状态,即它的成员变量;

(3)对象的持久化存储(写文件),网络传输对象,或者使用RMI都会用到对象序列化。



JAVA 提供的操作序列化的接口

(1)Java 主要提供给了两个接口实现对象的序列化和反序列化,java.io.ObjectInputStream的readObject()方法 和 java.io.ObjectOutputStream 的writeObject(Object obj)方法;

(2)只有实现Serializable或Externalizable接口的类的对象才能被序列化;否则会抛出java.io.NotSerializableException异常。



JAVA对象序列化示例


(1)类实现 Serializable接口

 类中未定义 writeObject(Object obj)和readObject方法,那么按照默认的序列化方式实现序列化和反序列化。


Student.java


Gender.java


SimpleSerializable.java

以上代码展示了如何序列化对象到一个文件中并从文件中反序列化的过程。

序列化的过程:

首先创建 ObjectOutputStream 对象,该对象可以包装其他输出流,比如文件输出流;

调用对象输出流的writeObject(Object obj)方法,可以将对象写入到输出流中。

关闭流。结束。

对象持久化到文件中的过程结束。

反序列化的过程:

首先创建ObjectInputStream对象,类似于ObjectOutputStream;

调用对象输入流的readObject()方法,读对象到输入流中。返回字节序列转化的对象。

关闭流;结束。

输出:

result



 类中定义了 writeObject(Object obj)和readObject方法,那么按照自定义的序列化方实现式序列化和反序列化。

在Student.java添加如下两个方法:


user-dined_read_write_Object

输出结果:

result2


(2)transient 关键字

  当某个成员变量声明为transient后,默认的序列化机制就会忽略该变量。

将age字段声明为transient,

transient

输出 age=0:

result3


此时我们可以选择单独传输某个字段;修改writeObject和readObject方法:


结果:

result4

单独传输了age 字段,因此age=18;

补充:除了上面提到的两个方法外:

private void writeObject(java.io.ObjectOutputStream out) throws IOException ;

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

还有其他三个方法,可供我们定制自己的序列化反序列化过程:

private void readObjectNoData() throws ObjectStreamException;

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

readObjectNoData() :用于初始化反序列化对象,当发生一些情况导致反序列化对象不能获得数据时调用;

writeReplace() 指派其他对象写入序列化的流中;

readResolve()返回的对象替换反序列化创建的实例;


readResolve() 常用于单例模式中;示例:

修改Student.java,添加instanceHoder:

Student.java


Student.java

修改SimpleSerial.java:


SimpleSerial.java

结果输出:

result5

可以看到,s==student返回false,也就是说反序列化后得到的Student对象并不是唯一的instance,因此这样写单例模式是失败的;

修正:

readResolve

再次运行:

result6


总结:

当进行序列化的时候:

首先JVM会先调用writeReplace方法,在这个阶段,我们可以进行张冠李戴,将需要进行序列化的对象换成我们指定的对象.

跟着JVM将调用writeObject方法,来将对象中的属性一个个进行序列化,我们可以在这个方法中控制住哪些属性需要序列化.

当反序列化的时候:

JVM会调用readObject方法,将我们刚刚在writeObject方法序列化好的属性,反序列化回来.

然后在readResolve方法中,我们也可以指定JVM返回我们特定的对象(不是刚刚序列化回来的对象).

注意到在writeReplace和readResolve,我们可以严格控制singleton的对象,在同一个JVM中完完全全只有唯一的对象,控制不让singleton对象产生副本.


(3)类实现Externalizable 接口 

   Externalizable 接口继承 Serializable接口: 

public interface Externalizable extends Serializable ;

Serializable接口是一个mark interface,没有实际方法;而Externalizable 接口提供了两个方法:

void  readExternal (ObjectInput in) ;

void  writeExternal (ObjectOutput out) ;

readExternal (ObjectInput in):从输入流中读取内容恢复对象;

writeExternal (ObjectOutput out) : 写入对象到输出流中;

示例:


Externalizable

使用Externalizable进行序列化时,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。因此,必须提供一个无参构造器,访问权限为public;否则会抛出java.io.InvalidClassException 异常;

总结:Externalizable接口实现的功能与Serializable接口类似,Serializable序列化时不会调用默认的构造器,而Externalizable序列化时会调用默认构造器;


感谢:深入理解Java对象序列化 - 51CTO.COM

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 在Java中,我们可以通过多种方式来创建对象,并且只要对象没有被回收我们都可以复用该对象。但是,我们创建出来的这些...
    懒癌正患者阅读 1,500评论 0 12
  • 序列化的意义 1.永久存储某个jvm中运行时的对象。2.对象可以网络传输3.rmi调用都是以序列化的方式传输参数 ...
    炫迈哥阅读 627评论 0 0
  • 什么是序列化与反序列化 序列化是指把对象转换为字节序列的过程(Encoding an object as a by...
    小X感悟阅读 865评论 0 4
  • java序列化与反序列化 对象序列化是一种持久化技术,广泛运用于网络传输、RMI等场景中。java对象存在于JVM...
    Crazy贵子阅读 624评论 0 0
  • 一、序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为对象的过程称为对象的反序列...
    叨唧唧的阅读 695评论 0 0