Java 中的序列化(Serialization)和反序列化(Deserialization),本质上是:
序列化:把 Java 对象转换成可以存储或传输的字节流
反序列化:把字节流再恢复成 Java 对象
一、为什么需要序列化
Java 对象默认只存在于 JVM 内存中。
比如:
User user = new User("Tom", 18);
这个 user 对象:
程序关闭后就消失
无法直接通过网络发送
无法直接写入文件
所以需要:
对象 → 字节流 → 保存到文件 / 网络传输 / 缓存
二、序列化流程图
Java对象
↓
序列化
↓
二进制字节流
↓
文件 / 网络 / Redis / 数据库
反过来:
二进制字节流
↓
反序列化
↓
Java对象
三、实现序列化的条件
Java 类必须实现:
Serializable
这是一个标记接口:
public interface Serializable {
}
没有方法,只是告诉 JVM:
👉 这个类可以被序列化
四、示例代码
1. 定义实体类
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " - " + age;
}
}
2. 序列化对象到文件
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SerializableTest {
public static void main(String[] args) throws Exception {
User user = new User("Tom", 18);
ObjectOutputStream out =
new ObjectOutputStream(new FileOutputStream("user.dat"));
out.writeObject(user);
out.close();
System.out.println("对象已序列化");
}
}
3. 反序列化对象
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class SerializableTest2 {
public static void main(String[] args) throws Exception {
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("user.dat"));
User user = (User) in.readObject();
in.close();
System.out.println(user);
}
}
输出:
Tom - 18
五、核心类
ObjectOutputStream
用于写对象:
writeObject()
例如:
out.writeObject(user);
ObjectInputStream
用于读对象:
readObject()
例如:
User user = (User) in.readObject();
六、serialVersionUID 的作用
通常建议写:
private static final long serialVersionUID = 1L;
完整写法:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
}
为什么需要它?
防止类修改后反序列化失败,相当于类的版本号。
例如:
第一次保存对象时类结构:
name
age
后来修改成:
name
age
email
JVM 会比较版本号:
serialVersionUID
如果不一致,就报错:
InvalidClassException

七、哪些字段不会序列化
1.加 transient
private transient String password;
表示:
👉 此字段不会被序列化
示例:
public class User implements Serializable {
private String name;
private transient String password;
}
序列化后:
password == null
2.static修饰的字段
static修饰的字段是静态字段(Static Field)或类变量(Class Variable)。它属于类级别而不是对象级别,随类加载而存在于方法区(或静态数据区),由所有该类实例所共享,能直接通过类名访问。就不是对象状态的一部分,因此不存在序列化与不序列化的问题。
八、实际应用场景
1. 网络传输
客户端发送对象到服务端:
User对象 → 字节流 → Socket → 服务端
2. Redis缓存
对象 → JSON/字节 → Redis
3. Session共享
Tomcat Session 持久化时:
Session对象 → 序列化 → 磁盘
4. 消息队列
对象 → 序列化 → MQ
九、常见异常
NotSerializableException
原因:
类没实现 Serializable
java.io.NotSerializableException
解决:
implements Serializable
十、JSON序列化 vs Java序列化
Java原生序列化
对象 → 二进制
优点:
简单
缺点:
不跨语言
性能一般
不安全
JSON序列化(更常用)
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
结果:
{"name":"Tom","age":18}
优点:
可读性高
跨语言
前后端通用
十一、相关问题
