目录
Java 序列化是一种将 Java 对象转换为字节序列的过程,这一过程主要用于将对象的状态持久保存到磁盘上,或通过网络传输到另一个运行 Java 的环境中。反序列化则是将这种字节序列恢复为 Java 对象。这种机制在多种场景下非常有用,比如在分布式系统中传输对象、保存对象状态以及进行深度复制等。
什么是 Java 序列化?
Java 序列化允许将对象转换成流,以便能够将其保存在数据库、文件或内存中,或者通过网络在不同的 JVM 之间传输。反序列化则是将已序列化的字节流重新构建成原来的对象。
如何实现 Java 序列化?
要实现 Java 序列化,你需要:
- 让你的类实现
java.io.Serializable
接口。 - 使用
ObjectOutputStream
将对象序列化。 - 使用
ObjectInputStream
将字节流反序列化成对象。
1. 实现 Serializable 接口
Serializable
是一个标记接口(没有方法的接口),用于使 Java 虚拟机(JVM)认识该类的对象可以被序列化。
import java.io.Serializable;
public class MyClass implements Serializable {
private static final long serialVersionUID = 1L; // 推荐添加这个版本号
// 类的成员变量和方法
}
2. 序列化对象
使用 ObjectOutputStream
类将对象写入到输出流。以下是一个示例:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo {
public static void main(String[] args) {
MyClass obj = new MyClass(); // MyClass 必须实现 Serializable 接口
try {
FileOutputStream fileOut = new FileOutputStream("object.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(obj);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in object.ser");
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 反序列化对象
使用 ObjectInputStream
类从文件中读取字节流并转换回原始对象。以下是一个示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializeDemo {
public static void main(String[] args) {
MyClass obj = null;
try {
FileInputStream fileIn = new FileInputStream("object.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
obj = (MyClass) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
System.out.println("MyClass class not found");
c.printStackTrace();
}
System.out.println("Deserialized MyClass...");
// 输出 obj 的内容
}
}
注意事项
-
非序列化成员: 使用
transient
关键字标记的成员变量不会被序列化。反序列化后,这些成员变量的值会被设为类型默认值(如null
、0
或false
)。 -
序列化 ID: 在每个可序列化的类中添加
private static final long serialVersionUID
字段是个好习惯。这个序列版本号可以帮助保证序列化对象的版本与反序列化时类的版本一致。 -
静态变量: 静态变量属于类的状态,不属于对象的状态,因此不会被序列化。
完整示例
下面是一个更完整的示例,使用一个简单的 Employee
类来展示序列化与反序列化的过程。
Employee.java
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
public String address;
public transient int SSN;
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " at " + address);
}
}
SerializeDemo.java
import java.io.*;
public class SerializeDemo {
public static void main(String[] args) {
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try {
FileOutputStream fileOut = new FileOutputStream("employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in employee.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
DeserializeDemo.java
import java.io.*;
public class DeserializeDemo {
public static void main(String[] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN); // 注意此处 SSN 为 0,因为它是 transient
System.out.println("Number: " + e.number);
}
}
通过这些步骤和示例,你应该能够理解和实现 Java 对象的序列化与反序列化,以便在不同的环境和程序间共享和存储对象状态。