在 Java 中,序列化是将对象的状态转换为字节流的过程,而反序列化则是从字节流中恢复对象的状态的过程。为了支持对象的序列化和反序列化,类需要实现 Serializable
接口。这个接口是一个标记接口,没有包含任何方法,主要是用来表示一个类的实例可以被序列化。
import java.io.Serializable;
public class MyClass implements Serializable {
// class definition
}
为什么要实现 Serializable
接口?
-
标记接口:
Serializable
接口是一个标记接口,用来表示类的实例可以被序列化。当一个类实现了Serializable
接口,表明该类的实例可以被转换为字节流,从而可以在网络上传输、保存到文件等场景中使用。 -
版本控制: 序列化涉及到对象的二进制表示形式,而在对象的类发生变更(例如添加、删除、修改字段)时,会影响对象的序列化和反序列化。为了在类发生变更时能够正确地进行版本控制,建议显式地声明一个名为
serialVersionUID
的字段。serialVersionUID
是一个 64 位长的private static final
字段,用于表明类的版本。如果不显式地声明serialVersionUID
,Java 编译器会根据类的结构自动生成一个,但这样一来,当类发生变更时,自动生成的版本号可能不同,导致序列化和反序列化失败。private static final long serialVersionUID = 1L;
总的来说,实现 Serializable
接口是为了表明类的实例可以被序列化,而显式地声明 serialVersionUID
则是为了进行版本控制,确保在类发生变更时能够正确地序列化和反序列化。
java序列化 返序列化 代码示例
以下是一个简单的 Java 序列化和反序列化的示例:
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
// 创建一个对象
Person person = new Person("John", 25);
// 序列化对象到文件
serializeObject(person, "person.ser");
// 反序列化对象
Person deserializedPerson = deserializeObject("person.ser");
// 打印反序列化后的对象信息
System.out.println("Deserialized Person: " + deserializedPerson);
}
// 序列化对象到文件
private static void serializeObject(Object obj, String fileName) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(obj);
System.out.println("Object serialized to " + fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
// 反序列化对象
private static <T> T deserializeObject(String fileName) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
@SuppressWarnings("unchecked")
T obj = (T) ois.readObject();
System.out.println("Object deserialized from " + fileName);
return obj;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
// 示例类,实现 Serializable 接口
private static 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 + '}';
}
}
}
这个示例中,Person
类实现了 Serializable
接口,然后创建了一个 Person
对象,将其序列化到文件 “person.ser” 中,接着再从文件中反序列化得到一个新的 Person
对象,并输出反序列化后的对象信息。在序列化过程中,使用 ObjectOutputStream
,而在反序列化过程中,使用 ObjectInputStream
。