前言
java 序列化是后端面试超高频考点,也是日常开发缓存、rpc、对象持久化的核心基础。看似只需实现一个空的 serializable 接口,但其中暗藏大量面试细节、版本兼容规则、继承机制与自定义序列化逻辑。
本文为 java 序列化系列・上篇(基础面试篇),主打零基础入门 + 面试全覆盖,搞定 90% 序列化基础面试题。
👉 循环引用、底层坑点、反序列化漏洞、生产最佳实践 进阶内容,请阅读下篇: java 序列化进阶:底层坑点、安全漏洞、生产实战与最佳实践
一、序列化与反序列化核心概念
1.1 基本定义
- 序列化:java 对象内存状态 → 可存储 / 可传输字节数组
- 反序列化:字节数组 → 还原为全新 java 对象
1.2 常见使用场景
- 对象持久化落地(文件、数据库)
- 网络 rpc、socket 传输对象
- redis 缓存对象存储
- 对象深拷贝(学习用,生产不推荐)
二、基础使用:serializable 入门
java 原生序列化核心依赖:标记接口 serializable
2.1 可序列化实体类
public class user implements serializable {
private string name;
private int age;
public user(string name, int age) {
this.name = name;
this.age = age;
}
// getter setter
}2.2 序列化代码
try (objectoutputstream oos = new objectoutputstream(new fileoutputstream("user.ser"))) {
oos.writeobject(new user("张三", 25));
}
2.3 反序列化代码
try (objectinputstream ois = new objectinputstream(new fileinputstream("user.ser"))) {
user user = (user) ois.readobject();
}
2.4 核心规则
- 没有实现 serializable 直接报错 notserializableexception
- 成员变量引用对象,也必须可序列化
- serializable 反序列化不会执行构造器
- 子类序列化、父类未序列化:会调用父类无参构造
三、serialversionuid 版本兼容(面试核心)
3.1 作用
用于 jvm 校验字节流与当前类是否版本匹配。
3.2 不手动写会怎样?
jdk 自动根据字段、方法、类结构生成版本号,轻微改代码版本号直接变,旧数据反序列化报错:invalidclassexception
3.3 最佳实践
所有序列化类必须手动固定版本号
private static final long serialversionuid = 1l;
3.4 版本兼容规则
- 新增字段:兼容(默认值填充)
- 删除字段:兼容(忽略多余数据)
- 修改字段类型:不兼容
- 修改包名 / 类名:完全不兼容
四、transient 与 static 序列化规则
4.1 transient
被 transient 修饰的字段 不参与序列化,反序列化后为默认值。
适用:密码、密钥、临时字段
4.2 static
静态字段属于类,不属于对象,永远不参与序列化
五、继承体系序列化规则
- 父类实现 serializable:子类自动序列化
- 父类未实现、子类实现
- 父类字段不会序列化
- 反序列化会调用父类无参构造器
- writeobject/readobject 是 private 方法 无继承性
六、自定义序列化:writeobject /readobject
默认序列化是全量反射,不够灵活,可以手动干预。
示例:敏感字段加密序列化
private transient string password;
private void writeobject(objectoutputstream out) throws ioexception {
out.defaultwriteobject();
out.writeutf(encrypt(password));
}
private void readobject(objectinputstream in) throws ioexception {
in.defaultreadobject();
this.password = decrypt(in.readutf());
}规则:
- defaultwriteobject /defaultreadobject 必须第一行执行
七、readresolve & writereplace 对象替换
writereplace
序列化之前替换对象,常用于代理模式
readresolve
反序列化之后替换返回对象,保护单例必备
private object readresolve() {
return instance;
}
八、externalizable 手动序列化
区别于 serializable 自动序列化:
- 完全手动控制字段读写
- 必须提供无参构造器
- transient 失效
- 性能更高、开发成本更高
九、特殊类型序列化坑点
9.1 枚举
- 枚举天然序列化
- serialversionuid 无效
- 只序列化名称,不序列化字段
- 天然单例安全
9.2 内部类、lambda
- 非静态内部类禁止序列化
- lambda 序列化兼容性极差,生产禁用
9.3 数组
数组可序列化,但内部元素必须可序列化
结语
本篇覆盖 java 序列化 90% 面试基础考点,适合面试突击、基础巩固。
到此这篇关于面试必问 java 序列化:serializable、transient、serialversionuid 完整梳理的文章就介绍到这了,更多相关 java 序列化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论