Serializable 接口

张开发
2026/5/19 22:26:58 15 分钟阅读
Serializable 接口
一、Serializable 接口是什么java.io.Serializable是 Java 标准库中的标记接口Marker Interface——没有任何方法、常量仅用来给 JVM 做标记实现它的类其对象允许被序列化 / 反序列化Oracle。不实现该接口调用ObjectOutputStream.writeObject()序列化时直接抛出NotSerializableExceptionOracle。它是 Java 原生对象序列化机制的入口配合ObjectOutputStream序列化、ObjectInputStream反序列化使用。二、核心概念序列化与反序列化序列化Serialization把内存中的 Java 对象转换成二进制字节流可写入文件、存入数据库、通过网络传输跨 JVM、跨服务。反序列化Deserialization把字节流重新还原成内存中的 Java 对象恢复对象状态。三、核心规则与关键细节1. 必须显式声明serialVersionUID强烈推荐private static final long serialVersionUID 1L; // 固定值不要自动生成作用版本校验。序列化时写入字节流反序列化时JVM 对比字节流中的值与当前类的serialVersionUID不一致则抛InvalidClassExceptionOracle。为什么必须显式不写时JVM 会根据类结构字段、方法、继承自动计算一个值类改一点加字段、改方法自动值就变旧序列化数据就无法反序列化Oracle。2. 哪些字段会被序列化默认所有非 static、非 transient 的实例字段递归序列化成员对象也必须实现 Serializable。transient关键字修饰的字段不参与序列化反序列化后为默认值null、0、false。static 静态变量属于类、不属于对象不序列化反序列化取当前类的最新值。3. 继承与序列化规则父类实现 Serializable → 所有子类自动可序列化Oracle。父类未实现 → 子类实现时父类字段不会被序列化反序列化时父类必须有无参构造方法否则抛异常父类字段会被初始化为默认值Oracle。4. 自定义序列化可选可在类中重写以下方法控制序列化 / 反序列化逻辑private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); // 先执行默认序列化 // 自定义额外写入 transient 字段、加密等 } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); // 先执行默认反序列化 // 自定义恢复 transient 字段、解密等 }四、完整代码示例import java.io.*; // 1. 实现 Serializable public class User implements Serializable { // 2. 显式声明 serialVersionUID private static final long serialVersionUID 123456789L; private String name; private int age; private transient String password; // 敏感字段不序列化 // 构造、getter/setter 省略 public static void main(String[] args) { User user new User(彭于晏, 30, 123456); // 序列化对象 → 字节流 → 文件 try (ObjectOutputStream oos new ObjectOutputStream(new FileOutputStream(user.ser))) { oos.writeObject(user); System.out.println(序列化完成); } catch (IOException e) { e.printStackTrace(); } // 反序列化文件 → 字节流 → 对象 try (ObjectInputStream ois new ObjectInputStream(new FileInputStream(user.ser))) { User deserializedUser (User) ois.readObject(); System.out.println(反序列化结果 deserializedUser.getName() , deserializedUser.getAge() , 密码transient deserializedUser.getPassword()); // 密码为 null } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }序列化完成 反序列化结果彭于晏, 30, 密码transientnull五、应用场景分布式 / 远程调用RMI、Dubbo、RPC 跨服务传对象持久化对象存文件、Redis 缓存、数据库深拷贝序列化再反序列化得到完全独立的对象副本会话存储Web 中 Session 钝化 / 活化六、注意事项与局限安全风险反序列化不可信数据极易被攻击构造恶意字节流执行代码必须做过滤 / 校验Oracle。性能一般、字节流不可读、跨语言差生产常用替代方案JSON、Protobuf、Kryo、Hessian。枚举默认实现 SerializableserialVersionUID固定为 0LOracle。

更多文章