反序列化java对象需用objectinputstream读取字节流并强转为目标类型,前提是类实现serializable、声明匹配的serialversionuid,且classpath中存在对应类。

从文件中反序列化 Java 对象,核心是用 ObjectInputStream 读取已序列化的字节流,并还原为原始对象实例。前提是该对象所属的类必须已实现 Serializable 接口,且运行时类路径中存在对应类的字节码。
反序列化前的必要准备
确保以下三点都满足,否则会抛出异常(如 ClassNotFoundException、InvalidClassException 或 EOFException):
- 目标类(及所有嵌套引用类型)已实现
java.io.Serializable - 类中显式声明了
private static final long serialVersionUID,且与序列化时一致 - 反序列化时,JVM 能在 classpath 中加载到该类(.class 文件不能缺失或版本错乱)
标准反序列化代码写法
使用 try-with-resources 安全打开流,避免资源泄漏:
注意:readObject() 返回 Object 类型,必须强制转为目标类型,否则编译不通过
try (FileInputStream fis = new FileInputStream("user.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
User user = (User) ois.readObject(); // 关键:强转还原
System.out.println(user);
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage());
} catch (ClassNotFoundException e) {
System.err.println("找不到类定义:" + e.getMessage());
}
常见问题与应对要点
-
文件为空或已损坏:触发
EOFException,建议先检查文件大小是否 > 0,或捕获该异常做降级处理 -
serialVersionUID 不匹配:抛
InvalidClassException,说明类结构变更后未更新版本号,应统一维护serialVersionUID - transient 字段值为 null/0:这是正常行为,反序列化时这些字段跳过恢复,按类型默认值初始化
-
父类未实现 Serializable:父类字段在反序列化后为默认值(如
null、0),子类字段正常还原
为什么不能直接 new ObjectInputStream(new FileInputStream(...)) 就完事?
因为 ObjectInputStream 构造时会尝试读取流头部的序列化协议标识(stream header)。如果文件不是由 ObjectOutputStream 写出的,或被手动修改过,构造就会立即失败并抛 StreamCorruptedException。所以务必确认文件来源可靠。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











