序列化是将 Java 对象的状态转换为字节流的过程。序列化后的字节流可以保存到文件、数据库,或通过网络传输。
主要用途:
如何实现:
对象要实现序列化,必须实现 java.io.Serializable
接口,这是一个标记接口(没有任何方法)。
示例:
import java.io.*;
class Person implements Serializable { // 实现 Serializable 接口
private static final long serialVersionUID = 1L;
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
// 序列化
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
out.writeObject(person);
System.out.println("Object serialized");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个示例中,Person
对象被序列化并保存到文件 person.ser
中。
反序列化是将字节流恢复为 Java 对象的过程。反序列化后的对象恢复了之前保存的状态。
示例:
import java.io.*;
public class Main {
public static void main(String[] args) {
// 反序列化
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person person = (Person) in.readObject();
System.out.println("Object deserialized");
System.out.println("Name: " + person.name);
System.out.println("Age: " + person.age);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
在这个示例中,Person
对象被反序列化,并恢复了之前保存的状态,输出对象的属性值。
serialVersionUID:
每个可序列化的类都隐式或显式地定义了一个 serialVersionUID
。它用于验证在反序列化期间,发送者和接收者的类版本是否兼容。如果没有显式定义,编译器会自动生成,但建议手动定义以避免不同版本间的冲突。
private static final long serialVersionUID = 1L;
transient 关键字:
被 transient
修饰的字段不会被序列化。这对于那些敏感信息或不需要持久化的字段非常有用。
示例:
class Person implements Serializable {
private static final long serialVersionUID = 1L;
String name;
transient int age; // age 字段不会被序列化
}
静态字段: 静态字段属于类而不属于对象,因此不会被序列化。
序列化和反序列化在网络通信、持久化和分布式系统中非常重要,使得对象的状态可以被保存和传递。