va 实现序列化与反序列化
序列化(Serialization) 是将 Java 对象转换为字节流(二进制数据),以便存储或网络传输。
反序列化(Deserialization) 则是将字节流恢复为 Java 对象。
Java 提供了 java.io.Serializable
接口来实现对象的序列化与反序列化。
1. 基本实现步骤
(1) 定义可序列化的类
类必须实现 Serializable
接口(标记接口,无方法)。
java
复制
下载
import java.io.Serializable;public class Person implements Serializable {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";} }
(2) 序列化(Object → 字节流)
使用 ObjectOutputStream
将对象写入文件或网络流。
java
复制
下载
import java.io.FileOutputStream; import java.io.ObjectOutputStream;public class SerializationExample {public static void main(String[] args) {Person person = new Person("Alice", 25);try (FileOutputStream fileOut = new FileOutputStream("person.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut)) {out.writeObject(person); // 序列化System.out.println("对象已序列化并保存到 person.ser");} catch (Exception e) {e.printStackTrace();}} }
(3) 反序列化(字节流 → Object)
使用 ObjectInputStream
从文件或网络流读取对象。
java
复制
下载
import java.io.FileInputStream; import java.io.ObjectInputStream;public class DeserializationExample {public static void main(String[] args) {try (FileInputStream fileIn = new FileInputStream("person.ser");ObjectInputStream in = new ObjectInputStream(fileIn)) {Person person = (Person) in.readObject(); // 反序列化System.out.println("反序列化结果: " + person);} catch (Exception e) {e.printStackTrace();}} }
运行结果:
复制
下载
反序列化结果: Person{name='Alice', age=25}
2. 进阶用法
(1) serialVersionUID
(版本控制)
-
用于确保序列化/反序列化的类版本一致,避免
InvalidClassException
。 -
如果类结构发生变化(如新增字段),但
serialVersionUID
不变,仍可兼容旧数据。
java
复制
下载
public class Person implements Serializable {private static final long serialVersionUID = 1L; // 手动指定版本号private String name;private int age;// ... }
(2) transient
关键字(禁止序列化字段)
java
复制
下载
public class Person implements Serializable {private String name;private transient int age; // 该字段不会被序列化// ... }
-
反序列化时,
transient
字段会恢复默认值(如int
→0
,String
→null
)。
(3) 自定义序列化(writeObject
和 readObject
)
java
复制
下载
private void writeObject(ObjectOutputStream out) throws IOException {out.defaultWriteObject(); // 默认序列化out.writeInt(age * 2); // 自定义处理(如加密) }private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject(); // 默认反序列化this.age = in.readInt() / 2; // 自定义处理(如解密) }
3. 常见问题
Q1: 哪些对象可以被序列化?
-
基本类型(
int
,String
,List
等)和实现了Serializable
的类。 -
static
字段不会被序列化(属于类,而非对象)。
Q2: 序列化后的文件内容可读吗?
-
是二进制格式,不可直接阅读,但可用
hexdump
或xxd
查看。 -
若需可读格式,可用 JSON(Gson/Jackson) 或 XML(JAXB) 替代。
Q3: 序列化安全吗?
-
不安全,二进制数据可能被篡改。
-
若需安全传输,可结合 加密(AES) 或 签名(RSA)。
4. 替代方案(JSON/XML 序列化)
(1) 使用 Gson(Google)
java
复制
下载
import com.google.gson.Gson;public class GsonExample {public static void main(String[] args) {Person person = new Person("Bob", 30);Gson gson = new Gson();// 序列化(Object → JSON)String json = gson.toJson(person);System.out.println("JSON: " + json); // {"name":"Bob","age":30}// 反序列化(JSON → Object)Person newPerson = gson.fromJson(json, Person.class);System.out.println("Object: " + newPerson);} }
(2) 使用 Jackson
java
复制
下载
import com.fasterxml.jackson.databind.ObjectMapper;public class JacksonExample {public static void main(String[] args) throws Exception {Person person = new Person("Charlie", 40);ObjectMapper mapper = new ObjectMapper();// 序列化(Object → JSON)String json = mapper.writeValueAsString(person);System.out.println("JSON: " + json);// 反序列化(JSON → Object)Person newPerson = mapper.readValue(json, Person.class);System.out.println("Object: " + newPerson);} }
总结
方式 | 特点 | 适用场景 |
---|---|---|
Java 原生序列化 | 二进制格式,高效,但不可读 | 本地存储、RMI |
JSON(Gson/Jackson) | 可读性强,跨语言兼容 | REST API、配置文件 |
XML(JAXB) | 结构化强,但冗长 | 旧系统、SOAP |
推荐:
-
优先用 JSON(易读、跨语言)。
-
若需高性能存储,用 Java 原生序列化。
-
避免序列化敏感数据(如密码),或使用加密。