Java 序列化和反序列化的核心作用是将对象转换为可存储或传输的字节流(序列化),以及从字节流恢复对象(反序列化)。以下是详细说明和示例:
作用
-
持久化存储
将对象保存到文件或数据库,重启后仍可恢复对象状态。 -
网络传输
在分布式系统中跨网络传输对象(如 RMI、Socket 通信)。 -
深拷贝
通过序列化实现对象的深拷贝,避免引用共享问题。
示例代码
1. 定义一个可序列化的类
import java.io.Serializable;public class Person implements Serializable {// 版本控制标识,确保序列化兼容性private static final long serialVersionUID = 1L;private String name;private transient int age; // transient 字段不会被序列化public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}
2. 序列化对象到文件
import java.io.*;public class SerializationDemo {public static void main(String[] args) {Person person = new Person("Alice", 30);// 序列化try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {oos.writeObject(person);System.out.println("对象已序列化到文件");} catch (IOException e) {e.printStackTrace();}}
}
3. 从文件反序列化对象
import java.io.*;public class DeserializationDemo {public static void main(String[] args) {// 反序列化try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {Person restoredPerson = (Person) ois.readObject();System.out.println("反序列化结果: " + restoredPerson);// 输出:Person{name='Alice', age=0}(age 是 transient,值为默认值 0)} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}
关键注意事项
-
实现
Serializable
接口
类必须显式实现Serializable
接口(标记接口,无方法)。 -
版本控制 (
serialVersionUID
)
显式定义serialVersionUID
避免因类结构变化导致反序列化失败。 -
transient
关键字
标记不需要序列化的字段(如敏感信息或临时状态)。 -
安全性
反序列化不可信数据可能导致安全漏洞(如反序列化攻击)。
常见应用场景
- 缓存系统:将对象序列化后存入 Redis 等缓存。
- RPC 框架:跨网络的远程方法调用(如 Dubbo)。
- Session 存储:Web 服务器将 Session 对象序列化后存储。
通过序列化,Java 实现了对象状态的持久化和跨环境传输,但需注意安全性和版本兼容性问题。