objectoutputstream/objectinputstream 是依赖序列化契约的二进制协议解析器,非万能对象流;乱码因写入的是含魔数(ac ed 00 05)的二进制数据,文本编辑会破坏结构;常见问题包括流未缓冲、顺序错乱、非可序列化字段、serialversionuid不匹配、transient跳过、读写顺序不一致及classnotfoundexception被吞。

ObjectOutputStream 和 ObjectInputStream 不是“能读写对象”的万能流,而是严格依赖序列化契约的二进制协议解析器——不满足条件时不会报错提示,而是静默失败或字段为 null/0。
为什么 writeObject() 后文件里全是乱码,且 readObject() 报 StreamCorruptedException?
因为它们写入的是带头部协议的二进制数据,不是文本;直接用记事本打开、编辑、另存为都会破坏魔数(AC ED 00 05)和后续结构。常见诱因:
- 没套
BufferedOutputStream/BufferedInputStream,尤其在 socket 场景下极易握手失败 - 写完没关流,或异常中断导致流头未完整写出
- 用
FileWriter或文本编辑器手动改过序列化文件(绝对禁止) - 服务端先建
ObjectInputStream、客户端先建ObjectOutputStream(顺序必须镜像)
类实现 Serializable 还是抛 NotSerializableException?
接口只是起点,真正校验发生在运行时:所有非 transient、非 static 字段的类型也必须可序列化。典型陷阱:
-
ArrayList<jsonobject></jsonobject>——org.json.JSONObject没实现Serializable,哪怕ArrayList本身可以 - 自定义类里引用了 Spring 的
ApplicationContext或 Jackson 的ObjectMapper - 忘了给内部类加
static(非静态内部类隐含持外部类引用,外部类也得可序列化)
readObject() 返回 Object,但强转后字段全是默认值?
这不是类型转换问题,而是反序列化中途失败的表象。最常见原因:
立即学习“Java免费学习笔记(深入)”;
- 没显式声明
private static final long serialVersionUID = 1L,类字段增删后 JVM 自动生成的新 UID 不匹配,抛InvalidClassException(但若 catch 了又没处理,就静默返回空对象) -
transient字段被跳过,反序列化后为null或0,不是 bug 是设计 - 写入顺序和读取顺序不一致:比如先
writeObject(u)再writeInt(100),读时却先调readInt(),就会错位读到对象字节流里去 -
ClassNotFoundException被吞掉(比如 log 了但没 throw),导致后续readObject()实际返回null
序列化不是“保存对象快照”,而是按固定协议编码字段值;它不调用任何构造方法,也不执行初始化块。一旦字段语义变更(如把 int age 改成 String ageDesc),旧数据就无法兼容——这点比 JSON 严格得多,也容易被忽略。










