转自:https://blog.csdn.net/calledWWW/article/details/79307706
阅读:https://blog.csdn.net/wdehxiang/article/details/77872506
一、什么是序列化和反序列化
序列化(Serialization)是一种将对象转化为字节序列的过程;
反序列化(Deserialization)是一种将字节序列重建成一个对象的过程。
二、对象的序列化主要有两种用途
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件或数据库中;
比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些session先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
2) 在网络上传送对象的字节序列。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
三、如何实现序列化
将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以序列化。
对象序列化包括如下步骤:
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));
- 1
2) 通过对象输出流的writeObject()方法写对象。
out.writeObject(“Hello”);
- 1
对象反序列化的步骤如下:
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 1
2) 通过对象输入流的readObject()方法读取对象。
String obj1 = (String)in.readObject();
- 1
注意事项:
对象的类名、属性会被序列化,方法不会被序列化。
transient修饰的属性和static属性不会被序列化。
要保证需要被序列化的属性也是可序列化的。
反序列化时,需要按照序列化顺序读取相应对象。
进行反序列话的JVM需要拥有序列化对象所属的类的class文件,且文件中的serializableID的值要相同,最好显示声明serializableID的值。
四、serialVersionUID的作用
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
常见的序列化协议有哪些
按照http://blog.csdn.net/a837199685/article/details/50611402整理到此处,具体可点击以上链接查看
- XML
- 定义
- XML(Extensible Markup Language)是一种常用的序列化和反序列化协议, 它历史悠久,从1998年的1.0版本被广泛使用至今。
- 优点
- 人机可读性好
- 可以指定元素或特性的名称
- 缺点
- 序列化数据只包含数据本身和类的结构,不包括类型标识和程序集信息。
- 类必须有一个将由 XmlSerializer 序列化的默认构造函数。
- 只能序列化公共属性和字段,不能序列化方法。
- 文件庞大,文件格式复杂,传输占带宽
- 使用场景
- 当作配置文件存储数据
- 实时数据转换
- 定义
- json(JavaScript Object Notation, JS 对象标记)
- 定义
- JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集, JSON采用与编程语言无关的文本格式,但是也使用了类C语言(包括C, C++, C#, Java, JavaScript, Perl, Python等)的习惯,简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
- 优点
- 前后兼容性高。
- 数据格式比较简单,易于读写。
- 序列化后数据较小,可扩展性好,兼容性好。
- 与XML相比,其协议比较简单,解析速度比较快。
- 缺点
- 数据的描述性比XML差。
- 不适合性能要求为ms级别的情况。
- 额外空间开销比较大。
- 使用场景
- 跨防火墙访问。
- 可调试性要求高的情况。
- 基于Web browser的Ajax请求。
- 传输数据量较小,实时性要求低(例如秒级别)的服务
- 定义
- Fastjson
- 定义
- Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致。
- 优点
- 接口简单易用。
- 目前Java中最快的json库。
- 缺点
- 过于注重快,而偏离了“标准”及功能性。
- 代码质量不高,文档不全
- 使用场景
- 协议交互。
- 文件输出。
- Android客户端。
- 定义
- Thrift
- 定义
- Thrift并不仅仅是序列化协议,而是一个RPC框架。它可以让你选择客户端与服务端之间传输通信协议的类别,即文本(text)和二进制(binary)传输协议, 为节约带宽,提供传输效率,一般情况下使用二进制类型的传输协议。
- 优点
- 序列化后的体积小, 速度快。
- 支持多种语言和丰富的数据类型。
- 对于数据字段的增删具有较强的兼容性。
- 支持二进制压缩编码。
- 缺点
- 使用者较少。
- 跨防火墙访问时,不安全。
- 不具有可读性,调试代码时相对困难。
- 不能与其他传输层协议共同使用(例如HTTP)。
- 无法支持向持久层直接读写数据,即不适合做数据持久化序列化协议。
- 使用场景
- 分布式系统的RPC解决方案
- 定义
- Avro
- 定义
- Avro属于Apache Hadoop的一个子项目。 Avro提供两种序列化格式:JSON格式或者Binary格式。Binary格式在空间开销和解析性能方面可以和Protobuf媲美,Avro的产生解决了JSON的冗长和没有IDL的问题。
- 优点
- 支持丰富的数据类型。
- 简单的动态语言结合功能。
- 具有自我描述属性。
- 提高了数据解析速度。
- 快速可压缩的二进制数据形式。
- 可以实现远程过程调用RPC。
- 支持跨编程语言实现。
- 缺点
- 对于习惯于静态类型语言的用户不直观
- 使用场景
- 在Hadoop中做Hive、Pig和MapReduce的持久化数据格式
- 定义
- Protobuf
- 定义
- protocol buffers 由谷歌开源而来,在谷歌内部久经考验。它将数据结构以.proto文件进行描述,通过代码生成工具可以生成对应数据结构的POJO对象和Protobuf相关的方法和属性。
- 优点
- 序列化后码流小,性能高。
- 结构化数据存储格式(XML JSON等)。
- 通过标识字段的顺序,可以实现协议的前向兼容。
- 结构化的文档更容易管理和维护。
- 缺点
- 需要依赖于工具生成代码。
- 支持的语言相对较少,官方只支持Java 、C++ 、Python。
- 使用场景
- 对性能要求高的RPC调用。
- 具有良好的跨防火墙的访问属性。
- 适合应用层对象的持久化。
- 定义
- 其他
- protostuff 基于protobuf协议,但不需要配置proto文件,直接导包即可。
- Jboss marshaling 可以直接序列化java类, 无须实java.io.Serializable接口。
- Message pack 一个高效的二进制序列化格式。
- Hessian 采用二进制协议的轻量级remoting onhttp工具。
- kryo 基于protobuf协议,只支持java语言,需要注册(Registration),然后序列化(Output),反序列化(Input)。
为什么java序列化接口没有方法却可以完成序列化
Serializable是一个所谓的标记接口,也就是说,实现这个接口是给这个类贴个标签,说它是Serializable的就可以了,具体实现是由JVM内部实现的,这个标签实际上是告诉JVM,你可以将我序列化。但这个标签不是随便贴的,如果你给一个类贴了这个标签,却在内部用到没贴这个标签的类,那运行时就可能有异常抛出。标记接口的用法现在一般被Annotation代替了,但Serializable是在Annotation还没出现前就存在了的。