序列化的几种常见方式
z在 Java 中,序列化(将对象转换为可传输 / 存储的格式)有多种实现方式,适用于不同场景(如网络传输、本地存储、跨语言交互等)。以下是常见的几种序列化方式及特点:
一、Java 原生序列化(JDK 自带)
原理:通过实现 java.io.Serializable
接口,使用 ObjectOutputStream
和 ObjectInputStream
进行对象与字节流的转换。特点:
- 仅适用于 Java 语言,不支持跨语言。
- 序列化后为二进制字节流,可读性差。
- 性能一般,且存在版本兼容性问题(需显式声明
serialVersionUID
避免反序列化失败)。
示例:
import java.io.*;// 实现Serializable接口
class User implements Serializable {private static final long serialVersionUID = 1L; // 显式声明版本号private String name;private int age;// 构造器、getter/setter省略
}// 序列化
public class NativeSerialization {public static void main(String[] args) throws IOException, ClassNotFoundException {User user = new User("zhangsan", 25);// 序列化到文件ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"));oos.writeObject(user);oos.close();// 反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"));User deserializedUser = (User) ois.readObject();ois.close();}
}
二、JSON 序列化(最常用,跨语言)
原理:将对象转换为 JSON 字符串(文本格式),通过 JSON 解析库实现,支持跨语言(Java、Python、JavaScript 等通用)。常用库:
- Jackson:Spring Boot 默认 JSON 库,性能好,功能全。
- Gson:Google 开发,API 简洁,易用性强。
- Fastjson:阿里巴巴开发,序列化速度快(但需注意版本安全性)。
特点:
- 文本格式,可读性强,便于调试。
- 跨语言兼容性好,是 HTTP 接口数据传输的首选。
- 不依赖 Java 特定接口,任何对象均可序列化(无需实现接口)。
示例(Jackson):
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;class User {private String name;private int age;// 构造器、getter/setter省略
}public class JsonSerialization {public static void main(String[] args) throws JsonProcessingException {User user = new User("zhangsan", 25);ObjectMapper objectMapper = new ObjectMapper();// 序列化:对象 → JSON字符串String json = objectMapper.writeValueAsString(user);System.out.println(json); // {"name":"zhangsan","age":25}// 反序列化:JSON字符串 → 对象User deserializedUser = objectMapper.readValue(json, User.class);}
}
三、XML 序列化(传统格式)
原理:将对象转换为 XML 标签格式,通过 XML 解析库实现,曾广泛用于 SOAP 协议、配置文件等。常用库:
- JAXB(Java Architecture for XML Binding):JDK 自带(Java 9 + 需手动引入依赖),通过注解(
@XmlRootElement
、@XmlElement
)映射对象与 XML。 - XStream:第三方库,无需注解,易用性高。
特点:
- 文本格式,可读性强,但比 JSON 冗余(标签多)。
- 适合传统企业级应用(如旧版 WebService),现在逐渐被 JSON 替代。
示例(JAXB):
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement // 标记为XML根元素
class User {private String name;private int age;// 构造器、getter/setter省略
}public class XmlSerialization {public static void main(String[] args) throws JAXBException {User user = new User("zhangsan", 25);JAXBContext context = JAXBContext.newInstance(User.class);// 序列化:对象 → XML字符串Marshaller marshaller = context.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化输出marshaller.marshal(user, System.out); // 输出:<user><name>zhangsan</name><age>25</age></user>// 反序列化:XML字符串 → 对象Unmarshaller unmarshaller = context.createUnmarshaller();User deserializedUser = (User) unmarshaller.unmarshal(...); // 从XML输入流读取}
}
四、Protocol Buffers(Protobuf,高性能二进制)
原理:由 Google 开发的二进制序列化格式,通过预定义 .proto
文件定义数据结构,生成对应语言的代码,实现高效序列化。
特点:
- 二进制格式,体积小(比 JSON/XML 小 30%-50%),序列化 / 反序列化速度极快(比 JSON 快 5-10 倍)。
- 跨语言支持(Java、C++、Python 等),适合高性能场景(如分布式系统、大数据传输)。
- 需预定义 schema(
.proto
文件),灵活性较低(schema 变更需重新生成代码)。
示例:
- 定义
.proto
文件(user.proto
):
syntax = "proto3";
message User {string name = 1;int32 age = 2;
}
2.生成 Java 代码(通过 Protobuf 编译器 protoc
),得到 User.java
。
3.序列化 / 反序列化
// 序列化
User user = User.newBuilder().setName("zhangsan").setAge(25).build();
byte[] bytes = user.toByteArray(); // 转换为字节数组// 反序列化
User deserializedUser = User.parseFrom(bytes);
五、其他方式
- Hessian:二进制序列化协议,适用于 Java 分布式系统(如 RPC 框架),性能优于 Java 原生序列化。
- Kryo:高性能 Java 序列化库,速度快、体积小,常用于缓存、分布式计算(如 Spark)。
- MsgPack:二进制 JSON,兼容 JSON 结构但体积更小,适合移动端 / 嵌入式场景。
六、选择建议
- 跨语言接口 / HTTP 传输:优先用 JSON(Jackson/Gson)。
- 高性能、大数据量场景:选 Protobuf 或 Kryo。
- 传统企业级应用 / XML 协议:用 JAXB。
- 仅 Java 环境、简单存储:可考虑 Java 原生序列化(但不推荐,性能和兼容性差)。