Java序列化
按照序列化后的数据格式,主流的序列化框架主要可以分为四大类:JSON、二进制、XML、RPC。
- JSON类
- 非常流行的Jackson
- Google的Gson
- 类JSON的MessagePack
- 阿里的FastJSON
- 二进制类
- 老牌劲旅Hessian
- 功能全面而强大的FST
- 后起之秀Kryo
- XML类
- StAX(Streaming API for XML)
- Thoughwork的XStream
- RPC类
- Protobuf:这里“偷了点懒”,因为Protobuf和Thrift都要安装、编译,所以这里使用了Protostuff,可以在运行时自动获取对象的Schema信息,省去了额外安装和手动编写协议格式文件的过程(Protostuff真是太好了!)。
- Thrift、Apache Avro:同上,都需要预编译。
Java序列化的作用
- 有的时候我们想要把一个Java对象变成字节流的形式传出去,有的时候我们想要从一个字节流中恢复一个Java对象。例如,有的时候我们想要把一个Java对象写入到硬盘或者传输到网路上面的其它计算机,这时我们就需要自己去通过java把相应的对象写成转换成字节流。对于这种通用的操作,我们为什么不使用统一的格式呢?没错,这里就出现了java的序列化的概念。在Java的OutputStream类下面的子类ObjectOutputStream类就有对应的WriteObject(Object object) 其中要求对应的object实现了java的序列化的接口。
- 实际开发中的应用场景
- 在使用tomcat开发JavaEE相关项目的时候,我们关闭tomcat后,相应的session中的对象就存储在了硬盘上,如果我们想要在tomcat重启的时候能够从tomcat上面读取对应session中的内容,那么保存在session中的内容就必须实现相关的序列化操作。
- 如果我们使用的java对象要在分布式中使用或者在rmi远程调用的网络中使用的话,那么相关的对象必须实现java序列化接口。
实现java对象的序列化和反序列化
Java对象的序列化有两种方式。
- 相应的对象实现了序列化接口Serializable,这个使用的比较多,对于序列化接口Serializable接口是一个空的接口,它的主要作用就是标识这个对象是可序列化的,jre对象在传输对象的时候会进行相关的封装。
- 实现序列化的第二种方式为实现接口Externalizable,Externlizable接口继承了java的序列化接口
实现Java的序列化接口需要注意一下几点:
- java中的序列化时transient变量(这个关键字的作用就是告知JAVA我不可以被序列化)和静态变量不会被序列
- 先序列化对象A后序列化B,那么在反序列化的时候一定记着JAVA规定先读到的对象是先被序列化的对象,不要先接收对象B,那样会报错.
- 实现序列化接口的对象并不强制声明唯一的serialVersionUID,是否声明serialVersionUID对于对象序列化的向上向下的兼容性有很大的影响。
- 其他
- 序列化时,只对对象的状态进行保存,而不管对象的方法;
- 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
- 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
- 并非所有的对象都可以序列化
如果没有明确指定serialVersionUID,序列化的时候会根据字段和特定的算法生成一个erialVersionUID,当属性有变化时这个id发生了变化,所以反序列化的时候就会失败。抛出“本地classd的唯一id和流中class的唯一id不匹配”。
实现序列化的其它方式
- 几种序列化方式比较
- FastJson
- FastJson是一个Json处理工具包,包括“序列化”和“反序列化”两部分,Fastjson是一个Java语言编写的高性能功能完善的JSON库。
- Fastjson支持java bean的直接序列化。 可以使用com.alibaba.fastjson.JSON这个类进行序列化和反序列化。
- FastJson确实在复杂对象序列化和反序列化方面做的比较好,而且速度和效率上都比java原生序列化机制要好。
- 但FastJson使用大对象或者大文件时,效果没有jackson好。你所以需要根据具体项目选择合适的序列化工具。