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
public interface Serializable {}

它是一个标记接口,用于告诉 JVM 这个类的对象可以被序列化。如果一个类不实现Serializable,使用Java自带的序列化时,会抛出异常。因此 Java 要求你必须显示地声明你允许对象被序列化。这个是Java原生的序列化机制,使用 ObjectOutputStreamObjectInputStream 来读写对象,Java 自动把对象转换为字节流或从字节流中恢复回来。

1
2
3
4
5
6
7
8
9
10
import java.io.Serializable;

public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
}

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("p.dat"));
out.writeObject(new Student());

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
2
3
4
5
6
{
"name": "Alice",
"age": 25,
"is_student": false,
"skills": ["Python", "Java", "C++"]
}

JSON原理

JAVA语言中可以使用Jackson库来做序列化/反序列化。JSON 使用 UTF-8来编码,底层存储时,JSON 实际是一个 UTF-8 字节流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import com.fasterxml.jackson.databind.ObjectMapper;

Person p = new Person();
p.name = "Alice";
p.age = 25;

// 创建 ObjectMapper(JSON 处理器)
ObjectMapper mapper = new ObjectMapper();

// 序列化
String jsonStr = mapper.writeValueAsString(p);
System.out.println(jsonStr); // 输出:{"name":"Alice","age":25}

// 反序列化
String jsonStr = "{\"name\":\"Alice\",\"age\":25}";
Person p = mapper.readValue(jsonStr, Person.class);

序列化时,Jackson 会使用 Java 的反射机制,找到这个类的所有字段和值,然后 Jackson 根据字段类型判断要怎么转换为 JSON 语法,最后构建 JSON 字符串。

XML

XML(eXtensible Markup Language) 是一种可扩展的标记语言,用于存储和传输数据。

XML示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 用子标签表示信息 -->
<person>
<name>Alice</name>
<age>25</age>
<skills>
<skill>Java</skill>
<skill>Python</skill>
</skills>
</person>

<!-- 也可以用属性表示信息 -->
<person age="25" name="Alice">
<city>Beijing</city>
</person>

Protobuf

Protocol Buffers(Protobuf) 是由 Google 开发的一种高效、结构化、跨语言的数据序列化协议。它把数据结构转换成紧凑的二进制格式,用于在网络中传输或存储。Protobuf 详细介绍


Java基础 - 序列化 & 反序列化
https://thiefcat.github.io/2025/07/06/JAVA/serialization-deserialization/
Author
小贼猫
Posted on
July 6, 2025
Licensed under