序列化:将 Java
对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存 Java
对象状态的过程,序列化可以将数据永久保存在磁盘上。
反序列化:将保存在磁盘文件中的 Java
字节码重新转换成 Java
对象称为反序列化。
省流:最核心的概念已在上面展示,如您还是不懂请往下看!
一、什么是序列化
序列化是指将对象转换为字节流的过程,以便可以在网络上传输或保存到文件中,反序列化则是将字节流转换回对象的过程。
在 Java 中,要使一个类可序列化,需要实现 java.io.Serializable
接口,以下是一个示例代码。
import java.io.*; class Person implements Serializable { 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; } } public class SerializationExample { public static void main(String[] args) { // 创建一个Person对象 Person person = new Person("Alice", 25); // 将对象进行序列化 try { FileOutputStream fileOut = new FileOutputStream("person.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(person); out.close(); fileOut.close(); System.out.println("对象已成功序列化到文件中!"); } catch (IOException e) { e.printStackTrace(); } // 将序列化后的对象进行反序列化 try { FileInputStream fileIn = new FileInputStream("person.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); Person deserializedPerson = (Person) in.readObject(); in.close(); fileIn.close(); System.out.println("从文件中反序列化得到的对象:"); System.out.println("姓名:" + deserializedPerson.getName()); System.out.println("年龄:" + deserializedPerson.getAge()); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
在上述代码中,Person
类实现了 Serializable
接口。首先,我们创建一个 Person
对象,并将其序列化到名为 person.ser
的文件中。然后,我们从文件中读取序列化的对象并进行反序列化,最终恢复了原始的 Person
对象。
请注意,在序列化和反序列化过程中,我们使用 ObjectOutputStream
和 ObjectInputStream
来分别写入和读取字节流。通过 writeObject()
方法将对象写入输出流,然后通过 readObject()
方法从输入流中读取对象。
运行上述代码,同学们将会得到以下输出。
对象已成功序列化到文件中! 从文件中反序列化得到的对象: 姓名:Alice 年龄:25
这个例子演示了 Java 中序列化和反序列化的基本概念和用法,通过序列化,我们可以方便地保存和传输对象数据,而不需要手动处理字节流。
二、什么是反序列化
反序列化是将对象从持久化状态恢复为内存中的对象的过程,在Java中,我们可以使用 ObjectInputStream
类来进行反序列化操作,下面是一个简单的示例代码。
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class DeserializationExample { public static void main(String[] args) { try { // 创建FileInputStream对象读取序列化后的对象 FileInputStream fileIn = new FileInputStream("serialized_object.ser"); // 创建ObjectInputStream对象读取对象 ObjectInputStream in = new ObjectInputStream(fileIn); // 反序列化对象 Person person = (Person) in.readObject(); // 输出反序列化后的对象信息 System.out.println("姓名:" + person.getName()); System.out.println("年龄:" + person.getAge()); // 关闭输入流 in.close(); fileIn.close(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
在上述示例中,我们从名为 serialized_object.ser
的文件中读取序列化后的对象,并通过 ObjectInputStream
进行反序列化。然后,我们将恢复的 Person
对象的属性打印到控制台上。
请注意,在进行反序列化之前,必须确保序列化和反序列化过程中使用的类具有相同的 serialVersionUID
。否则,在反序列化时可能会引发 InvalidClassException
。
三、为什么要进行序列化和反序列化
3.1 主要目的
Java 进行序列化和反序列化的主要目的是在不同的场景中实现对象的持久化和数据传输。
- 持久化:通过序列化,可以将对象保存到磁盘或数据库中,以便在程序重启后恢复对象的状态。这对于需要长时间存储对象或进行数据持久化的应用程序非常有用。
- 数据传输:通过序列化,可以将对象转换为字节流,在网络上传输或进行远程方法调用。序列化使得在分布式系统中传递对象变得更简单,可以轻松地在客户端和服务器之间传递对象,并确保对象的完整性和一致性。
- 缓存和缓存共享:通过序列化,可以将对象存储在缓存中,以提高性能。对象可以被序列化后存储在内存或磁盘上,当需要时可以快速从缓存中加载而无需重新创建对象。
- 对象传递:通过序列化,可以方便地在进程之间传递对象。在多线程编程或分布式系统中,通过将对象序列化并传递给其他线程或进程,可以实现数据共享和通信。
总的来说,序列化和反序列化提供了一种机制,可以将对象转换为字节流,以便持久化、传输和共享数据。它在许多应用程序中被广泛使用,包括数据库操作、网络通信和分布式系统等。
3.2 应用场景
序列化和反序列化在许多应用场景中起到关键作用,以下是一些常见的应用场景:
缓存:将对象序列化后,可以将其存储在缓存中,以提高性能和响应速度。当需要时,可以从缓存中快速加载对象,而无需重新创建或计算。
分布式系统:在分布式系统中,对象需要在不同的节点之间传递。通过将对象序列化为字节流,可以在网络上进行传输,并在远程服务之间共享数据。
持久化:通过序列化,可以将对象保存到文件、数据库或其他持久化存储中。这样,在应用程序重启后,可以从存储中读取序列化的对象并还原其状态。
远程方法调用:通过序列化和反序列化,可以在不同的计算机上执行远程过程调用。客户端将请求参数序列化为字节流,发送给远程服务器,服务器接收到字节流后进行反序列化,执行相应的方法,并将结果序列化并返回给客户端。
数据传输和消息传递:在网络通信中,通过将对象序列化为字节流,可以轻松地传输和接收复杂的数据结构、消息和事件。
克隆对象:通过序列化和反序列化,可以实现对象的深度克隆。序列化对象后,创建一个完全独立的副本。
需要注意的是,在某些场景下,使用序列化和反序列化可能会带来性能上的开销,因此,在设计应用程序时,需要权衡考虑序列化和反序列化的成本与收益,并根据具体需求选择合适的方案。
四、总结
序列化是将Java对象以一连串的字节保存在磁盘文件中的过程,序列化可以将数据永久保存在磁盘上;反序列化是将保存在磁盘文件中的Java字节码重新转换成Java对象的过程。
本文对 Java 的序列化和反序列化进行了介绍,讲解了如何在实际业务中使用序列化和反序列化,并给出了 Java 样例代码。在下一篇博客中,将讲解 Java 中的正则表达式规则和使用方式。