今天,我将结合实战经验,带大家深入了解几种常见的Java序列化方式,并通过示例代码展示它们的使用方法和效果。
什么是序列化?
在Java中,我们经常看到实体类或POJO实现Serializable接口。这个空接口只是一个标记,用于告诉JVM该对象可以被序列化。简单来说,序列化就是将对象转换为二进制字节流,以便在网络传输或持久化存储中使用。反序列化则是将这个二进制字节流还原为对象。序列化的主要目的是实现对象的跨平台存储和网络传输。
常见的序列化方式
1. JSON
JSON是目前最流行的序列化方式之一,尤其在前后端交互中广泛使用。它的可读性高,跨平台、跨语言支持良好。不过,JSON的体积相对较大,因为包含了很多冗余内容,如双引号和花括号。
示例代码:
使用阿里提供的fastjson库进行JSON序列化和反序列化:
import com.alibaba.fastjson.JSON;
public class JsonExample {
public static void main(String[] args) {
User user = new User(1, "Alice");
// 序列化
String jsonString = JSON.toJSONString(user);
System.out.println("Serialized JSON: " + jsonString);
// 反序列化
User deserializedUser = JSON.parseObject(jsonString, User.class);
System.out.println("Deserialized User: " + deserializedUser);
}
}
class User {
private int id;
private String name;
// Constructor, getters, and setters
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "'}";
}
}
运行结果:
Serialized JSON: {"id":1,"name":"Alice"}
Deserialized User: User{id=1, name='Alice'}
2. XML
XML曾经是配置文件和Web服务中常用的格式,但现在逐渐被注解和JSON取代。不过,在一些老系统中,如广电或银行系统,仍然大量使用XML。
示例代码:
使用Java内置的JAXB库进行XML序列化和反序列化:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
public class XmlExample {
public static void main(String[] args) throws JAXBException {
User user = new User(1, "Bob");
// 序列化
JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
StringWriter writer = new StringWriter();
marshaller.marshal(user, writer);
String xmlString = writer.toString();
System.out.println("Serialized XML: " + xmlString);
// 反序列化
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xmlString);
User deserializedUser = (User) unmarshaller.unmarshal(reader);
System.out.println("Deserialized User: " + deserializedUser);
}
}
// User class with JAXB annotations (not shown for brevity)
注意:User类需要添加JAXB注解,如@XmlRootElement、@XmlElement等。
运行结果(简化版):
Serialized XML:
Deserialized User: User{id=1, name='Bob'}
3. Protobuf
Protobuf是谷歌提出的一种高效序列化协议。它使用二进制格式,体积小,传输速度快。
示例代码:
首先,定义一个.proto文件:
syntax = "proto2";
package com.demo;
message User {
required int32 id = 1;
required string name = 2;
}
使用protoc生成Java代码,然后在Java中使用:
import com.demo.UserProto.User;
public class ProtobufExample {
public static void main(String[] args) {
// 创建User对象
User.Builder userBuilder = User.newBuilder();
userBuilder.setId(1);
userBuilder.setName("Charlie");
User user = userBuilder.build();
// 序列化
byte[] serializedUser = user.toByteArray();
System.out.println("Serialized Protobuf: " + java.util.Arrays.toString(serializedUser));
// 反序列化
try {
User deserializedUser = User.parseFrom(serializedUser);
System.out.println("Deserialized User: id=" + deserializedUser.getId() + ", name=" + deserializedUser.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果(二进制数据将显示为字节数组):
Serialized Protobuf: [some byte array]
Deserialized User: id=1, name=Charlie
4. Thrift
Thrift是Facebook提出的一种序列化协议和RPC框架,使用方式与Protobuf类似。由于篇幅限制,这里不详细展开,但基本流程是定义.thrift文件,生成代码,然后在Java中使用。
序列化协议选择
在选择序列化协议时,需要考虑以下几个因素:
可读性:如果需要人类可读,JSON和XML是不错的选择。性能:对于微服务间的数据传输,Protobuf和Thrift通常更高效。兼容性:考虑系统间的语言和技术栈支持。学习成本:JSON几乎零学习成本,而Protobuf和Thrift需要学习特定的DSL。
在实际项目中,我通常会根据具体场景选择序列化方式。例如,前后端交互使用JSON,微服务间通信使用Protobuf或Thrift。希望这篇实战分享能对你有所帮助,在选择和使用序列化协议时更加得心应手。