什么是序列化和反序列化?
什么是序列化和反序列化?
- 序列化和反序列化是计算机科学中两个重要的概念,主要应用在数据存储和网络传输等场景。
- 序列化是将数据结构或对象状态转换为可以存储或传输的形式的过程。这种形式要求在重新构建原始对象时能够在其他环境或在程序运行的后续时间点使用。这个过程主要通过将对象的数据转化为字节流来实现,也可以将其转化为格式如 XML 或 JSON 的数据,以便在网络上进行传输或在磁盘上进行存储。
- 举个例子,假设你有一个复杂的数据结构,如一个包含多个字段和数组的对象。你不能直接将这个对象写入文件或通过网络发送。因此,你需要先将其转换为可以写入或发送的格式,这就是序列化。
- 反序列化是序列化的逆过程,也就是从一系列字节中提取出数据结构。在接收到序列化的数据(如从文件或网络)后,通过反序列化,可以将数据恢复为原始的对象或数据结构,从而可以在程序中使用。
- 以上述的例子,反序列化就是读取该文件或接收到的数据,并根据序列化时的格式将其恢复为原始的对象。
- 这两个过程在很多编程语言中都有内置的支持,例如在 Java 中,你可以使用
java.io.Serializable
接口来对对象进行序列化和反序列化;在 Python 中,你可以使用pickle
模块进行序列化和反序列化;在 JavaScript 中,你可以使用 JSON 的stringify
和parse
方法进行序列化和反序列化等。
在java中实现序列化和反序列化,为什么要实现Serializable
接口?
-
Serializable
接口是一种标记接口,本身并没有定义任何方法,但是它向 JVM 提供了一个指示,表明实现该接口的类可以被序列化和反序列化。这意味着你可以将该类的对象转换为字节流(序列化),然后再将这个字节流转回为对象(反序列化)。 - 序列化的过程是 JVM 通过反射来完成的,它会查看对象的类是否实现了
Serializable
接口。如果没有实现,将会抛出一个NotSerializableException
异常。 - 实现
Serializable
接口的主要原因如下:
- 允许 JVM 序列化对象:如上所述,JVM 只会序列化实现
Serializable
接口的对象。 - 表示类的实例可以被安全地序列化:实现
Serializable
接口的类表示它满足 JVM 对于序列化的要求。这不仅仅是类的实例可以被转换为字节流,还包括这个类的实例可以被反序列化,而且反序列化后的对象保持了原始对象的状态。 - 允许类的实例在 JVM 之间进行传输:序列化的一个重要应用是在网络应用或分布式系统中,允许对象在 JVM 之间进行传输。只有实现
Serializable
接口的对象才能通过网络进行传输。 - 持久化:序列化也被用于将对象的状态持久化,即将对象存储在数据库、文件或内存中,然后在需要的时候再进行恢复。实现
Serializable
接口的对象可以被持久化。
- 综上,实现
Serializable
接口是为了使对象可以被序列化和反序列化,以便在不同的环境或时间点恢复对象的状态,或在 JVM 之间传输对象,或将对象的状态持久化。
案例
- 当然可以。下面这个简单的例子中,我们将创建一个实现了
Serializable
接口的类Person
,然后进行序列化和反序列化: - 首先,我们创建一个实现了
Serializable
接口的Person
类:
import java.io.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
对象的类SerializeDemo
:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SerializeDemo {
public static void main(String[] args) {
Person p1 = new Person("John Doe", 30);
try {
FileOutputStream fileOut = new FileOutputStream("/tmp/person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(p1);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/person.ser");
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 现在我们来反序列化这个
Person
对象,创建一个类DeserializeDemo
:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class DeserializeDemo {
public static void main(String[] args) {
Person p = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
p = (Person) in.readObject();
in.close();
fileIn.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Deserialized Person...");
System.out.println("Name: " + p.getName());
System.out.println("Age: " + p.getAge());
}
}
- 以上就是一个完整的 Java 序列化和反序列化的例子。首先我们创建了一个
Person
对象并序列化到一个文件中,然后我们从这个文件中读取数据并反序列化回Person
对象。