Java基础 - 序列化 & 反序列化
背景
UTF-8
Unicode Transformation Format – 8-bit,用于在计算机中表示世界上所有的文字字符。
最早的编码是用ASCII,用一个字节(8位)表示字符,但它最多只能表示 128 个字符,不能表示世界上所有语言和符号。UTF-8 使用 1到4个字节 来编码一个字符,向后兼容 ASCII(前128个字符完全一样)。它是目前最广泛使用的字符编码,尤其是在网络、网页、编程语言中。
Definition
序列化就是把一个在内存中的数据对象(如变量、对象、数据结构)转换成一个可以存储或传输的格式的过程。在程序运行中,对象位于内存,如果想要把对象保存到硬盘、发送到网络、或写入文件,你必须把它转换成一种通用格式,比如 JSON、XML、或二进制流,这就是序列化。
反序列化是把序列化后的数据重新变成程序能使用的对象的过程。
序列化/反序列化方法
java.io.Serializable
java.io.Serializable 是 Java 自带的二进制序列化机制,用于在 Java 内部保存/传输对象(不像JSON是跨语言的)。
定义:
1 |
|
它是一个标记接口,用于告诉 JVM 这个类的对象可以被序列化。如果一个类不实现Serializable,使用Java自带的序列化时,会抛出异常。因此 Java 要求你必须显示地声明你允许对象被序列化。这个是Java原生的序列化机制,使用 ObjectOutputStream
和 ObjectInputStream
来读写对象,Java 自动把对象转换为字节流或从字节流中恢复回来。
1 |
|
transient
使用 transient 关键字修饰的字段将被序列化机制完全忽略。它不会被写入字节流,因此在反序列化后,该字段将被赋予其类型的默认值。
serialVersionUID
如果你将一个对象序列化之后保存在磁盘或数据库中,过了一段时间后,你修改了这个类的结构(比如新增字段或删除字段),然后你尝试从旧的数据反序列化回对象,这时如果 serialVersionUID 不匹配,Java 会报错。如果你不自动加上这个字段,JVM 会根据类结构自动生成 serialVersionUID,但是如果修改了一个方法签名、改了注释、改了访问权限,都会生成不同的 ID,因此建议手动写死 serialVersionUID,以避免版本冲突。
在反序列化时,JVM 会比较流中对象的 serialVersionUID 和本地加载的类的 serialVersionUID。如果两者不匹配,将抛出 java.io.InvalidClassException。
JSON
JSON (JavaScript Object Notation),是一个纯文本格式的数据容器。几乎所有的 Web API 都使用 JSON 作为数据交换标准,许多应用也用 .json
文件保存设置
1 |
|
JSON原理
JAVA语言中可以使用Jackson库来做序列化/反序列化。JSON 使用 UTF-8来编码,底层存储时,JSON 实际是一个 UTF-8 字节流。
1 |
|
序列化时,Jackson 会使用 Java 的反射机制,找到这个类的所有字段和值,然后 Jackson 根据字段类型判断要怎么转换为 JSON 语法,最后构建 JSON 字符串。
XML
XML(eXtensible Markup Language) 是一种可扩展的标记语言,用于存储和传输数据。
XML示例:
1 |
|
Protobuf
Protocol Buffers(Protobuf) 是由 Google 开发的一种高效、结构化、跨语言的数据序列化协议。它把数据结构转换成紧凑的二进制格式,用于在网络中传输或存储。Protobuf 详细介绍