NotSerializableException最常见,触发于序列化未实现Serializable接口的类或其非transient成员;InvalidClassException在反序列化时因serialVersionUID不匹配或类结构不兼容变更抛出;ClassNotFoundException因反序列化时classpath缺失对应类而发生。

Java 对象序列化过程中会根据具体错误类型抛出不同异常,不是统一 throw 一个异常,而是由 ObjectOutputStream 或 ObjectInputStream 在执行时动态抛出明确的子类异常。
常见序列化异常及触发条件
以下是最常遇到的几类异常,每种都对应明确的错误场景:
-
NotSerializableException:最常见。当尝试序列化一个未实现
java.io.Serializable接口的类(或其某个非transient成员对象未实现该接口)时立即抛出。例如:new ObjectOutputStream(out).writeObject(new Date())不会报错(Date可序列化),但若传入自定义类MyData却没加implements Serializable,就立刻触发此异常。 -
InvalidClassException:反序列化时抛出。典型原因是类的
serialVersionUID与序列化时保存的值不一致,或类结构发生不兼容变更(如删除字段、修改字段类型)。即使类实现了Serializable,只要版本号对不上,ois.readObject()就会失败。 - ClassNotFoundException:反序列化时抛出。表示字节流中记录的类名,在当前 JVM 的 classpath 中找不到对应类定义。比如用旧版本程序序列化的对象,拿到新环境(缺少该类或 jar 包)里反序列化就会报这个错。
-
IOException(及其子类如
FileNotFoundException、StreamCorruptedException):底层 I/O 出问题。例如文件被占用、磁盘满、流被提前关闭,或读取的文件根本不是合法的序列化数据(内容损坏/被篡改)。
异常不是“主动 throw”,而是操作失败时自动抛出
你不需要手动写 throw new NotSerializableException()。只要调用 ObjectOutputStream.writeObject() 或 ObjectInputStream.readObject(),JVM 就会在检测到上述任一违规时,自动抛出对应的具体异常。所以实际编码中必须用 try-catch 捕获这些受检异常(IOException 和 ClassNotFoundException 是必须处理的;NotSerializableException 和 InvalidClassException 是 RuntimeException 的间接子类,但实践中仍建议捕获并提示明确原因)。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
怎么让异常信息更有用
光靠异常类型还不够,关键看堆栈和消息细节:
立即学习“Java免费学习笔记(深入)”;
- 打印完整异常:用
e.printStackTrace()或日志框架输出,第一行就含异常类名和简要描述(如java.io.NotSerializableException: com.example.User)。 - 检查嵌套对象:如果报的是某个成员字段不可序列化,说明问题不在主类本身,而在它的某个引用对象(比如字段是
Thread、Socket或第三方库中的非序列化类)。 - 确认
serialVersionUID是否显式声明:没声明时 JVM 会自动生成,但极易因类微小改动而变化。建议所有可序列化类都加上private static final long serialVersionUID = 1L;并随兼容性升级手动调整。

















