Java 中常用的序列化方式主要包括以下几种:
1. Java 原生序列化
使用方式:
使用 java.io.Serializable 接口。对象需要实现该接口,然后通过 ObjectOutputStream 和 ObjectInputStream 进行序列化和反序列化。
示例代码:
import java.io.*;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// 构造方法、getter 和 setter 方法
public static void main(String[] args) {
Person person = new Person("John", 30);
// 序列化(`FileOutputStream` 是一个字节流类,用于将数据写入文件。在这里,它指定了文件名 `"person.ser"`)
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
oos.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person deserializedPerson = (Person) ois.readObject();
System.out.println(deserializedPerson.getName() + ", " + deserializedPerson.getAge());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
底层实现原理:
- Java 原生序列化采用的是从对象中提取字段数据,并将这些数据以字节流的形式存储下来。
ObjectOutputStream将对象转换为字节流,ObjectInputStream将字节流恢复为对象。- 序列化过程中,Java 会记录对象类型信息和对象引用关系,以支持复杂对象图的序列化和反序列化。
2. JSON 序列化
使用方式:
使用第三方库,如 FastJson、Jackson 或 Gson,将对象转换为 JSON 字符串,再将 JSON 字符串还原为对象。
示例代码(使用 Jackson):
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonExample {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
Person person = new Person("John", 30);
// 序列化
try {
String jsonString = mapper.writeValueAsString(person);
System.out.println(jsonString);
// 反序列化
Person deserializedPerson = mapper.readValue(jsonString, Person.class);
System.out.println(deserializedPerson.getName() + ", " + deserializedPerson.getAge());
} catch (IOException e) {
e.printStackTrace();
}
}
}
底层实现原理:
- 利用反射机制,根据对象的字段信息生成相应的 JSON 格式字符串。
- 反序列化时,这些库会解析 JSON 字符串,并利用反射创建对象实例并赋值给其字段。
3. ProtoBuf 序列化
使用方式:
使用 Google 的 Protocol Buffers(ProtoBuf)来定义消息格式,并生成相应的 Java 类。
示例代码:
首先定义一个 .proto 文件:
syntax = "proto3";
message Person {
string name = 1;
int32 age = 2;
}
然后使用 protoc 工具生成 Java 类,并进行序列化/反序列化:
import com.example.PersonOuterClass.Person;
public class ProtoBufExample {
public static void main(String[] args) {
Person person = Person.newBuilder().setName("John").setAge(30).build();
// 序列化
byte[] byteArray = person.toByteArray();
// 反序列化
try {
Person deserializedPerson = Person.parseFrom(byteArray);
System.out.println(deserializedPerson.getName() + ", " + deserializedPerson.getAge());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
}
底层实现原理:
- ProtoBuf 采用预定义的二进制格式,具有良好的跨语言兼容性。
- 在编译
.proto文件时,会生成对应的 Java 类,这些类包含序列化和反序列化的方法。 - ProtoBuf 在序列化时会将数据按照字段编号编码成紧凑的二进制格式,反序列化时则根据字段编号恢复对象数据。