如果我们需要持久化 Java 对象,比如将 Java 对象保存在文件中,或者在网络传输 Java 对象,这些场景都需要用到序列化。序列化需要使用到序列化器
在Java中,Serializer(序列化器)是一个广义的概念,指的是将对象状态转换为可存储或可传输格式的过程的工具或组件。它并不是特指某一个框架,而是一种设计模式或功能,可以由不同的库或框架提供。
Java提供了内置的序列化机制(实现java.io.Serializable接口),但也有很多第三方库提供了更高效、跨语言的序列化方案,如JSON(Jackson、Gson)、XML、Protocol Buffers、Kryo等。
下面分别介绍几种常见的序列化方式。
一、Java内置序列化(基于Serializable接口)
使用步骤:
- 让需要序列化的类实现java.io.Serializable接口(标记接口,没有方法)。
- 使用ObjectOutputStream和ObjectInputStream进行序列化和反序列化。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import java.io.*;
class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
@Override public String toString() { return "Person{name='" + name + "', age=" + age + "}"; } }
public class JavaSerializationExample { public static void main(String[] args) { Person person = new Person("Alice", 30);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) { oos.writeObject(person); System.out.println("序列化完成"); } catch (IOException e) { e.printStackTrace(); }
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) { Person deserializedPerson = (Person) ois.readObject(); System.out.println("反序列化结果: " + deserializedPerson); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
|
注意:
- transient关键字:标记的成员变量不参与序列化。
- serialVersionUID:用于控制版本,如果序列化和反序列化的版本不一致,会抛出InvalidClassException。
二、JSON序列化(以Jackson为例)
使用Jackson库进行JSON序列化和反序列化。
首先,添加Jackson依赖(Maven):
1 2 3 4 5
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> </dependency>
|
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonExample { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person("Alice", 30);
String jsonString = objectMapper.writeValueAsString(person); System.out.println("JSON字符串: " + jsonString);
Person deserializedPerson = objectMapper.readValue(jsonString, Person.class); System.out.println("反序列化对象: " + deserializedPerson); } }
|
注意:Person类此时不需要实现Serializable接口,但需要有默认构造方法和getter/setter方法(或者通过注解配置)。
三、其他序列化框架
- Gson:Google提供的JSON库,用法类似。
- Protocol Buffers(protobuf):Google推出的跨语言、高性能的序列化框架,需要先定义.proto文件。
- Kryo:专注于Java对象序列化,性能高,但跨语言支持弱。
选择序列化方式时,需考虑以下因素:
- 性能:序列化/反序列化的速度、字节大小。
- 可读性:是否需要人类可读的格式(如JSON、XML)。
- 跨语言:是否需要支持多种编程语言。
- 兼容性:协议是否向前向后兼容。
四、自定义序列化
在Java内置序列化中,可以通过在类中实现writeObject和readObject方法来自定义序列化过程。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class CustomPerson implements Serializable { private String name; private int age;
private void writeObject(ObjectOutputStream out) throws IOException { String encryptedName = "加密后的名字"; out.writeObject(encryptedName); out.writeInt(age); }
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { String encryptedName = (String) in.readObject(); this.name = "解密后的名字"; this.age = in.readInt(); } }
|
总结:
Java中序列化的使用方式多样,根据需求选择合适的序列化框架。内置序列化简单但性能不高,且跨语言能力差;JSON序列化可读性好且跨语言;Protobuf等二进制协议性能高,适合网络传输。