使用ObjectInputStream反序列化对象的前提是对象及其所有字段类型均实现Serializable接口,且文件由ObjectOutputStream正确序列化生成;需声明serialVersionUID、用transient标记非序列化字段、父类也须可序列化;应通过try-with-resources打开流并捕获IOException和ClassNotFoundException,readObject()返回Object需强制转换;注意静态/transient字段不恢复、类变更可能导致异常、不可信数据反序列化有安全风险。

使用 ObjectInputStream 从文件中反序列化对象,核心前提是该对象及其所有字段类型都实现了 Serializable 接口,且文件是之前用 ObjectOutputStream 正确序列化生成的。
确保类可序列化
被反序列化的类必须显式实现 java.io.Serializable 接口。虽然接口无方法,但它标记了 JVM 可以安全地将对象状态写入/读出字节流:
- 推荐为每个可序列化类声明
private static final long serialVersionUID = 1L;,避免因类结构变更导致InvalidClassException - 不想被序列化的字段应加
transient修饰符(如数据库连接、线程等运行时资源) - 父类也需可序列化,否则会抛
NotSerializableException
正确打开输入流并反序列化
用 FileInputStream 包装目标文件,再套一层 ObjectInputStream,调用 readObject() 方法即可。注意处理异常和资源关闭:
- 必须捕获
IOException和ClassNotFoundException(反序列化时若类在当前类路径中不存在,会抛此异常) - 推荐使用 try-with-resources 自动关闭流,避免资源泄漏
-
readObject()返回的是Object类型,需强制转换为原始类型(建议配合泛型工具方法或检查 instanceof)
常见问题与注意事项
反序列化不是“万能还原”,存在实际限制和安全隐患:
- 静态字段和 transient 字段不会恢复,值为默认值(
null、0、false等) - 若序列化后修改了类(如删字段、改访问修饰符),可能抛
InvalidClassException或静默丢失数据 - 不验证来源的反序列化存在严重安全风险(如远程代码执行),生产环境慎用,尤其不要反序列化不可信数据
- 枚举、Lambda 表达式、匿名内部类等特殊类型支持有限,部分场景会失败
简单示例代码
假设有一个 User 类已实现 Serializable:
try (FileInputStream fis = new FileInputStream("user.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
User user = (User) ois.readObject();
System.out.println(user.getName());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}

















