Java 序列化

摘要: 序列化: 将对象变为可传输内容的过程就是序列化.方式: 1、Java原生: 简介 Java原生序列化实体类必须实现Serializable接口。 原理是通过Java原生流(InputStream和OutputStream)的方式进行转化。

序列化:

将对象变为可传输内容的过程就是序列化.
方式:

1、Java原生:

简介

Java原生序列化实体类必须实现Serializable接口。
原理是通过Java原生流(InputStream和OutputStream)的方式进行转化。
java原生序列化存在的问题
...

1) 序列化数据结果比较大、传输效率比较低;

2) 不能跨语言对接.

以至于在后来的很长一段时间,基于XML格式编码的对象序列化机制成为了主流,一方面解决了多语言兼容问题,
另一方面比二进制的序列化方式更容易理解。

再到后来,基于JSON的简单文本格式编码的HTTP REST接口又基本上取代了复杂的Web Service接口,
成为分布式架构中远程通信的首要选择。但是JSON序列化存储占用的空间大、性能低。

恰当的序列化协议不仅可以提高系统的通用性、强壮型、安全性、优化性能。同时还能让系统更加易于调试和扩展

2、Json序列化

Json序列化一般会使用jackson包,通过ObjectMapper类来进行一些操作,比如将对象转化为byte数组或者将json串转化为对象。
现在的大多数公司都将json作为服务器端返回的数据格式。比如调用一个服务器接口,通常的请求为xxx.json?a=xxx&b=xxx的形式。
3、FastJson序列化

fastjson 是由阿里巴巴开发的一个性能很好的Java 语言实现的 Json解析器和生成器。
特点:速度快,测试表明fastjson具有极快的性能,超越任其他的java json parser。
功能强大,完全支持java bean、集合、Map、日期、Enum,支持范型和自省。无依赖,能够直接运行在Java SE 5.0以上版本, 支持Android。
使用时候需引入FastJson第三方jar包。
4、ProtoBuff序列化

ProtocolBuffer是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化。
适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
优点:跨语言;序列化后数据占用空间比JSON小,JSON有一定的格式,在数据量上还有可以压缩的空间。
缺点:它以二进制的方式存储,无法直接读取编辑,除非你有 .proto 定义,否则无法直接读出 Protobuffer的任何内容。
其与thrift的对比:两者语法类似,都支持版本向后兼容和向前兼容,thrift侧重点是构建跨语言的可伸缩的服务,支持的语言多,同时提供了全套RPC解决方案,
可以很方便的直接构建服务,不需要做太多其他的工作。 Protobuffer主要是一种序列化机制,在数据序列化上进行性能比较,Protobuffer相对较好。
serialVersionUID的作用

  • 不实现Serializable接口的类不能被序列化, 会抛出NotSerializableException异常

  • 实现Serializable接口, 但没有定义serialVersionUID值, 反序列化可能会出现local class incompatible异常

    这是基于Java的安全机制. 当序列化对象时, 如果该对象所属类没有serialVersionUID, Java编译器会对jvm中该类的Class文件进行摘要算法生成一个
    serialVersionUID(version1). 保存在序列化结果中. 当反序列化时, jvm会再次对jvm中Class文件摘要生成一个serialVersionUID(version2). 当且仅当被序列化对象的version1=version2时,
    才会将反序列化结果加载入jvm中, 否则视为不安全, 抛出local class incompatible异常.
    这样存在的问题就是, 当对象被序列化后, 其所属类只要进行过任何改动,会导致摘要算法算出的serialVersionUID变化.
    从而version1 != version2导致抛出异常.
    例如序列化对象存储在磁盘中后, jvm停止, 并且对其所属类进行修改. 再次启动jvm, 当对该对象序列化时就会抛异常.
    不参与序列化

静态变量不参与序列化 (序列化不保存静态变量的状态)

被Transient修饰的成员变量不参与序列化

父子类中, 如果父类没有序列化, 子类序列化时, 父类的成员不会参与序列化

这种情况多出现在继承关系, 将common的一些属性定义在父类, 当父类没有实现Serializable接口的情况下, 序列化子类时, 父类成员属性不会参与到序列化中去.
有员工做抽象时, 将公共属性放在父类, 但父类没有实现Serializable接口, 导致了自雷序列化时丢失属性, 进而项目报错, 找半天错才发现.

存储规则

同一对象多次写入同一文件时, 只会保存一个序列化后的对象a以及多个对a的引用

当同一个文件, 例如b. 当一个对象c多次在b文件中写入时, 不会保存多个序列化后的对象, 只会保存第一个被序列化后的对象d. 再次存储c时, 存储内容为d的引用.
如果再次存储时成员属性发生变化, 例如age值由1变为2, 那么本次存储会增加d的引用以及成员变化值.请添加链接描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章