在现代分布式系统中,序列化和反序列化是不可或缺的环节。它们用于将对象转换为可传输的字节流,并在接收端重建对象。本文将探讨几种常见的序列化方式,包括JSON、Java原生序列化和Protobuf,并通过实例代码进行性能对比。
我们将使用一个简单的类 Cat 进行序列化和反序列化测试。Cat 类包含两个属性:name 和 age。
- import java.io.*;
-
- class Cat implements Serializable {
- private String name;
- private int age;
-
- // Constructors, getters, and setters
-
- public Cat(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- // toString method
- @Override
- public String toString() {
- return "Cat{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
- }
我们使用 Jackson 库进行JSON序列化和反序列化。
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- public class JsonSerialization {
- private static ObjectMapper objectMapper = new ObjectMapper();
-
- public static String serialize(Cat cat) throws IOException {
- return objectMapper.writeValueAsString(cat);
- }
-
- public static Cat deserialize(String json) throws IOException {
- return objectMapper.readValue(json, Cat.class);
- }
- }
Java原生序列化和反序列化
- public class NativeSerialization {
- public static byte[] serialize(Cat cat) throws IOException {
- try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos)) {
- oos.writeObject(cat);
- return bos.toByteArray();
- }
- }
-
- public static Cat deserialize(byte[] data) throws IOException, ClassNotFoundException {
- try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
- ObjectInputStream ois = new ObjectInputStream(bis)) {
- return (Cat) ois.readObject();
- }
- }
- }
首先,定义Protobuf的 .proto 文件:
- syntax = "proto3";
-
- message Cat {
- string name = 1;
- int32 age = 2;
- }
生成Java类后:
- import com.google.protobuf.InvalidProtocolBufferException;
- import example.CatProto.Cat;
-
- public class ProtobufSerialization {
- public static byte[] serialize(Cat cat) {
- return cat.toByteArray();
- }
-
- public static Cat deserialize(byte[] data) throws InvalidProtocolBufferException {
- return Cat.parseFrom(data);
- }
- }
我们通过以下代码进行性能测试:
- import java.io.IOException;
- import java.util.Arrays;
-
- public class SerializationPerformanceTest {
- public static void main(String[] args) throws IOException, ClassNotFoundException {
- Cat cat = new Cat("Whiskers", 3);
-
- // JSON
- long jsonStart = System.nanoTime();
- String json = JsonSerialization.serialize(cat);
- Cat jsonCat = JsonSerialization.deserialize(json);
- long jsonEnd = System.nanoTime();
- System.out.println("JSON time: " + (jsonEnd - jsonStart));
-
- // Native
- long nativeStart = System.nanoTime();
- byte[] nativeData = NativeSerialization.serialize(cat);
- Cat nativeCat = NativeSerialization.deserialize(nativeData);
- long nativeEnd = System.nanoTime();
- System.out.println("Native time: " + (nativeEnd - nativeStart));
-
- // Protobuf
- example.CatProto.Cat protoCat = example.CatProto.Cat.newBuilder().setName("Whiskers").setAge(3).build();
- long protoStart = System.nanoTime();
- byte[] protoData = ProtobufSerialization.serialize(protoCat);
- example.CatProto.Cat protoCatDeserialized = ProtobufSerialization.deserialize(protoData);
- long protoEnd = System.nanoTime();
- System.out.println("Protobuf time: " + (protoEnd - protoStart));
- }
- }
根据测试结果,Protobuf的序列化和反序列化性能优于JSON和Java原生序列化。虽然JSON的可读性强,但在性能和体积上,Protobuf更具优势。因此,在对性能和体积有较高要求的场景下,推荐使用Protobuf进行序列化。
通过以上实例代码和测试结果,我们可以更好地理解不同序列化方式的优缺点,并根据具体需求选择合适的序列化方式。