在 Java 中,序列化(Serialization)和反序列化(Deserialization)是两个重要的概念,它们主要用于将对象转换为字节流(序列化)以及将字节流恢复为对象(反序列化)。这在对象的存储、网络传输等场景中非常有用。如下图:

序列化是指将一个 Java 对象转换为字节序列的过程,这个字节序列可以被保存到文件、数据库,或者通过网络传输到其他地方。反序列化则是序列化的逆过程,它将字节序列恢复为原来的 Java 对象。
序列化的主要用途包括:
对象持久化:将对象保存到文件、数据库中,以便后续恢复使用。
远程方法调用(RMI):在分布式系统中,通过网络传输对象。
对象复制:通过序列化和反序列化可以实现对象的深拷贝。
要使一个类的对象能够被序列化,该类必须实现 java.io.Serializable 接口。Serializable 接口是一个标记接口,它没有任何方法,只是用来表明实现该接口的类可以被序列化。
以下是一个简单的可序列化类的示例:
package com.hxstrive.java_io.serializable;
import java.io.Serializable;
/**
* 实现 Serializable 接口
*/
public 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;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}在上述代码中,Person 类实现了 Serializable 接口,并且定义了一个 serialVersionUID 常量。serialVersionUID 用于在反序列化时验证序列化对象的版本一致性,如果不指定,Java 会根据类的结构自动生成一个。
要将一个对象序列化,可以使用 ObjectOutputStream 类。以下是一个示例:
package com.hxstrive.java_io.serializable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("John", 30);
try (FileOutputStream fos = new FileOutputStream("person.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
// 写入对象
oos.writeObject(person);
System.out.println("对象已序列化");
} catch (IOException e) {
e.printStackTrace();
}
}
}运行示例,输出:

在上述代码中,首先创建了一个 Person 对象,然后使用 FileOutputStream 和 ObjectOutputStream 将该对象写入到名为 person.ser 的文件中。
要将一个序列化的对象恢复为原来的对象,可以使用 ObjectInputStream 类。以下是一个示例:
package com.hxstrive.java_io.serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializationExample {
public static void main(String[] args) {
final String userDir = System.getProperty("user.dir");
try (FileInputStream fis = new FileInputStream(userDir + File.separator + "person.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
// 读取对象
Person person = (Person) ois.readObject();
System.out.println("对象已反序列化: " + person);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}运行结果:
对象已反序列化: Person{name='John', age=30}在上述代码中,使用 FileInputStream 和 ObjectInputStream 从 person.ser 文件中读取对象,并将其转换为 Person 类型。
如果一个类的某个字段被声明为 transient,那么在序列化时该字段将被忽略。例如:
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient int age; // 该字段不会被序列化
// 构造方法、getter 和 setter 方法
}在进行序列化和反序列化时,建议显式地指定 serialVersionUID,以确保在类的结构发生变化时,仍然能够正确地进行反序列化。