externalizable接口要求开发者完全接管序列化:必须提供public无参构造器,手动实现writeexternal和readexternal方法,严格保证读写顺序、类型、数量一致,精准控制字段存取以提升性能。

实现 Externalizable 接口是 Java 中彻底接管序列化行为的方式——不依赖 JVM 自动遍历字段,而是由你手动决定写什么、怎么写、怎么读回来。
必须提供 public 无参构造器
反序列化时,JVM 会用反射调用这个构造器创建新实例,而不是复用原有对象。它必须存在且为 public,哪怕内容为空。
- 构造器里可以设默认值(如
status = ACTIVE),但此时所有字段仍是初始值(null、0、false) - 不要在其中访问尚未恢复的字段,也不应触发远程初始化或耗时逻辑
- 若父类也实现了 Externalizable,子类构造器无需特殊处理,但
readExternal中需显式调用super.readExternal(in)
重写 writeExternal:只写真正需要的数据
在这个方法里,你逐个调用 out.writeXXX() 把字段写入流。没写的,就完全不会出现在字节中——不占空间、不传网络、不存磁盘。
- 跳过计算字段(如
getFullName())、缓存字段(如cacheMap)、临时状态(如isProcessing) - 敏感字段(如
passwordHash)只要不调用out.writeXXX(),就不会泄露 - 可主动加轻量元信息:开头写版本号
out.writeInt(2),便于后续兼容升级
重写 readExternal:严格镜像 writeExternal
读取顺序、类型、次数,必须和写入完全一致。错一位、混一个类型,运行时就会抛 StreamCorruptedException 或类型转换异常。
- 如果写了版本号,先读
int version = in.readInt(),再按版本分支决定后续读哪些字段 - 引用类型(如
List<string></string>)用in.readObject(),前提是写入时用了out.writeObject() - 不能漏读、不能多读、不能换顺序——哪怕只是把
writeUTF和writeInt调换了位置,也会失败
和 Serializable 的本质区别
Externalizable 不是 Serializable 的“增强版”,而是另一条路:放弃所有默认机制,包括字段自动保存、父类字段继承、transient 语义、serialVersionUID 兼容检查等。
- 不调用
defaultWriteObject,也不走反射遍历,没有元数据开销 - 没有自动处理父类字段,全靠你在两个方法里显式写/读
- 适合对性能、安全、协议格式有强要求的场景,比如跨语言通信、高频缓存、敏感数据隔离
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











