关注△mikechen的架构笔记△,十余年BAT架构经验倾囊相授
大家好,我是mikechen。
序列化方式常见的有5种,包含:Java序列化、Hessian、Json等序列化方式,下面我一一来详解@mikechen
最新mikechen原创超30万字《阿里架构师进阶专题合集》和《最全大厂面试题及答案总结》,请关注本公众号【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等序列化进行详解,希望对你掌握序列化有所帮助。
以上
最后送大家一个福利:
送我原创超30万字阿里架构师进阶专题合集。
以及给大家整理最全大厂Java面试题及答案详解,包含:Java、多线程、JVM、Spring、MySQL、Redis、中间件...等必考题答案详解。
需要以上架构专题&面试答案的同学,加我微信即可领取!
添加时备注:资料