Real-Time Example for Serialization in Java

2025年3月27日 | 阅读 4 分钟

Java 中的序列化是指将对象转换为字节流的机制,以便可以将其写入文件、通过网络发送或存储在数据库中。序列化的反向过程是反序列化,通过反序列化可以从字节流中重建对象。

实时示例:保存用户偏好设置

我们以一个业务文本编辑器为例,这是一个桌面应用程序,允许用户设置特定的选项,例如字体大小、背景或前景色、语言等。因此,为了将这些设置锁定为一个在多个会话中保持不变的值,应用程序可以将其存储在磁盘上的用户偏好设置序列化,并在同一会话中调用应用程序时反序列化。

问题概述

鉴于此,最好确保每次用户更改应用程序中的设置时,都能妥善管理这些设置,以便在每次使用应用程序时都能保留其各自的偏好。然后,可以使用序列化来存储用户状态,并在每次运行应用程序时加载这些设置。

序列化的好处是什么?

持久性:它允许对象的状态被存储并在以后检索。例如,应用程序中的某些用户偏好设置可以存储起来,然后在任何时候从文件中检索,以避免用户默认其设置。

通信:可以将对象序列化,然后通过网络传递到另一个 Java 虚拟机(JVM)。这在分布式应用程序中尤其适用,其中对象交换在各种组件或服务之间进行。

缓存:可以将对象序列化并存储在缓存中以节省一些时间。例如,在 Web 应用程序中,可以序列化并缓存用户会话,从而不必从头开始重新创建它们。

克隆:可以看出,通过序列化,可以在复制过程中开发出更复杂的 对象。利用序列化和反序列化的概念,可以重新创建具有与原始对象相同状态的新对象。

关于 Java 中的序列化,有几点需要注意

serialVersionUID:Serializable 接口不要求实现类定义特定的标识符值,并且每个类都必须定义此值,以确保后续反序列化的版本兼容性。如果未提供字面量,则 JVM 会根据类的结构创建一个,如果之后更改了类,则可能产生不同的值,从而导致兼容性问题。

Transient 和 Static 字段:具有 transient 属性的字段不会被序列化。static 字段也是如此,它们不是对象状态的一部分,因此也不会被序列化。这纠正了存储敏感信息甚至不相关信息的可能性。

安全性:当使用从不受信任的源序列化并检索到的对象时,需要考虑安全性,因为它允许代码执行。一种方法是序列化数据需要得到正确的验证和过滤。

继承:如果一个类实现了 java.io.Serializable 合同,那么所有子类本身都是 Serializable 的。反过来,如果超类不实现 Serializable,那么在序列化过程中必须处理其字段。

Java 中序列化的规则是,为了使一个对象能够被序列化,它必须实现 Serializable 接口,这是一个空接口。

下面是一个 UserPreferences 类的示例。

文件名:SerializationExample.java

输出

Real-Time Example for Serialization in Java

注意事项和边缘情况

版本控制:在这种特定情况下,如果在序列化后对 UserPreferences 类进行了一些修改。例如,添加或删除字段,甚至更改其名称,则后续的反序列化过程可能会导致失败,或者产生不希望的结果,除非 serialVersionUID 也得到了适当的处理。

敏感数据:不要序列化密码等敏感数据。如果是这种情况,应将这些字段标记为 transient,或者在序列化之前对数据进行加密。

结论

序列化是一项 Java 功能,旨在保存和传输对象的状态,因此是实时应用程序中持久性、通信和缓存的重要工具。该示例展示了如何序列化和反序列化用户的偏好设置,以便用户在上次活跃的会话结束后不必重新开始设置。