要让类实现externalizable接口需提供public无参构造器,并重写public的writeexternal和readexternal方法,手动控制字段序列化与反序列化,transient失效,不兼容serializable机制。

要让类实现 Externalizable 接口来完全控制序列化读写,核心是放弃默认机制,自己动手处理所有字段的写入与还原——它不是 Serializable 的增强版,而是一条更底层、更自主的路径。
必须提供 public 无参构造器
反序列化时 JVM 会先调用这个构造器创建空对象,再执行 readExternal 填充字段。即使你平时只用有参构造,也得显式补上:
- 构造器必须是 public,不能是 private 或 package-private
- 可以为空,但不能缺失;如果需要初始化默认状态(如空集合、标志位),可放在这里
- 注意:此时字段仍是初始值(null / 0 / false),别依赖它们做逻辑判断
重写 writeExternal 和 readExternal 方法
这两个方法是 Externalizable 的灵魂,必须都实现,且访问修饰符为 public:
-
writeExternal 中按需调用
out.writeInt()、out.writeUTF()等,只写真正需要持久化的字段 -
readExternal 必须严格按 相同顺序、相同类型、相同数量 调用对应读取方法,错一位就可能抛
StreamCorruptedException - 父子类都实现 Externalizable 时,子类中需显式调用
super.writeExternal(out)和super.readExternal(in)
跳过字段靠手动省略,transient 失效
Externalizable 不认 transient 关键字,也不自动过滤任何字段:
- 想跳过密码、缓存、计算属性?直接不在 writeExternal 里写它就行
- 想加版本号或校验字段?在 writeExternal 开头写
out.writeByte(2),readExternal 开头读并分支处理 - 不要在读写逻辑里动态增减字段(比如用 if 判断是否写某个字段),除非两端完全对称,否则极易出错
不兼容默认序列化机制
Externalizable 是独立协议,和 Serializable 的规则互不干涉:
-
serialVersionUID对它无效,版本兼容全靠你在流里自定义标识和分支逻辑 - 不会自动保存父类字段、静态字段、或任何未显式写出的内容
- 适合精简体积、加密压缩、对接二进制协议等场景,但维护成本更高,每次改字段都要同步更新两个方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











