序列化的5种方式详解(非常全面)

序列化的5种方式详解(非常全面)-mikechen

序列化方式常见的有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面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法