序列化方式常见的有5种,包含:Java序列化、Hessian、Json等序列化方式,下面我一一来详解@mikechen
1.Java原生序列化
Java类通过实现Serializable接口来实现该类对象的序列化,如下代码示例:
public class TestBean implements Serializable { private Integer id; private String name; private Date date; //省去getter和setter方法和toString }
这个接口非常特殊,没有任何方法,只起标识作用,Java序列化保留了对象类的元数据(如类、成员变量、继承类信息等),以及对象数据等,兼容性最好,但不支持跨语言,而且性能一般。
实现Serializable接口的类建议设置serialVersionUID字段值,如果不设置,那么每次运行时,编译器会根据类的内部实现,包括类名、接口名、方法和属性等来自动生成serialVersionUID。
如果类的源代码有修改,那么重新编译后serial VersionUID的取值可能会发生变化。
因此实现Serializable接口的类一定要显式地定义serialVersionUID属性值。
import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID = 1234567890L; private int id; private String name; public Person(int id, String name){ this.id = id; this.name = name; } public String toString(){ return "Person: " + id + " " + name; } }
2.Hessian 序列化
Hessian 序列化是一种支持动态类型、跨语言、基于对象传输的网络协议。
Hessian 序列化特性:
- 自描述序列化类型,不依赖外部描述文件或者接口定义,用一个字节表示常用的基础类型,极大缩短二进制流;
- 语言无关,支持脚本语言;
- 协议简单,比Java原生序列化高效;
- 相比hessian1,hessian2中增加了压缩编码,其序列化二进制流大小是Java序列化的50%,序列化耗时是Java序列化的30%,反序列化耗时是Java序列化的20%。
在使用Hessian序列化之前,需要在maven工程中,引入Hessian依赖:
<dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.62</version> </dependency>
无论jdk序列化,还是hessian序列化,实体类均需要实现Serializable接口。
具体代码示例:
public class Test { public static void main(String[] args) throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); Hessian2Output output = new Hessian2Output(os); output.writeObject(Person.hehe(123L, "wangyong")); output.close(); ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray()); Hessian2Input input = new Hessian2Input(in); System.out.println(input.readObject()); } } class Person implements Serializable { private Long id; private String name; private Person(long id, String name) { this.id = id; this.name = name; System.out.println("call dd"); } public static Person hehe(Long id, String name) { Person p = new Person(id, name); return p; } @Override public String toString() { return "id=" + id + ", name=" + name; } }
更多参考官方:http://hessian.caucho.com/doc/hessian-serialization.html
3.Json序列化
关于Json 可以说是web 开发不管是前端还是后端都是非常的熟悉,JSON是一种轻量级的数据交换格式。
JSON 序列化就是将数据对象转换为 JSON 字符串,在序列化过程中抛弃了类型信息,相比前两种方式,JSON 可读性比较好,方便调试。
Json语法规则:
- 数据在键值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
具体示例如下:
{ "employees": [ { "firstName":"Mike" , "lastName":"Chen" }, { "firstName":"Anna" , "lastName":"Smith" }, { "firstName":"Peter" , "lastName":"Jones" } ] }
4.ProtoBuf
谷歌推出的,是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于通信协议、数据存储等。
Protobuf应用场景
序列化后体积小,一般用于对传输性能有较高要求的系统,Protobuf序列化方式适用于跨语言通信、对码流大小和性能要求高、且pojo不经常变化的场景。
Protobuf使用
要想使用Protobuf就需要先定义proto文件,先熟悉protobuf消息定义的相关语法。
定义消息类型,示例如下:
syntax = "proto3"; message SendRequest { string query = 1; int32 page_number = 2; repeated int32 result_per_page = 3; }
- .proto文件的第一行指定了使用proto3语法,说明使用的是proto3版本,如果省略protocol buffer编译器就默认使用proto2语法;
- message表示消息类型,可以有多个;
- SendRequest定义中指定了三个字段(name/value键值对),每个字段都会有名称和类型;
- repeated是字段规则。
5.Kryo
Kryo 是一个 Java 序列化框架,号称 Java 最快的序列化框架,Kryo 在序列化速度上很有优势,底层依赖于字节码生成机制。
Kryo 的特点:
- 序列化的性能非常高
- 序列化结果体积较小
- 提供了简单易用的API
但是由于只能限定在 JVM 语言上,所以 Kryo 不支持跨语言使用。
Kryo序列化被很多开源项目使用,社区非常活跃:
- Apache Hive
- Apache Spark
- Twitter’s Chill
- Storm
- akka-kryo-serialization
Kryo序列化具体示例如下:
static void quickStart() throws FileNotFoundException { Kryo kryo = new Kryo(); Output output = new Output(new FileOutputStream("file.bin")); SomeClass someObject = new SomeClass(); someObject.setValue("this is someObject."); kryo.writeObject(output, someObject); output.close(); Input input = new Input(new FileInputStream("file.bin")); SomeClass deSomeObject = kryo.readObject(input, SomeClass.class); input.close(); Assert.assertEquals(someObject.getValue(), deSomeObject.getValue()); }
序列化方式小结
本文主要对几种常见序列化方式:Java原生序列化、Hessian、Json、Protobuff、Kryo等序列化进行详解,希望对你掌握序列化有所帮助。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》