除了将对象写入/读取文件之外,Serializable的使用方式是什么?

24

除了将对象写入/读取文件之外,在哪些情况下实现Serializable是良好的编码实践?在一个项目中,我看到一个类实现Serializable,即使在该类/项目中没有任何将对象写入/从文件读取的操作。


1
请注意,实现Serializable并不像看起来那么简单。它会破坏封装性,代表了一个超语言机制用于对象创建,并可能导致安全漏洞。它会导致本应该隐藏的实现细节作为类API的一部分被导出。对于某些类,必须非常小心地开发良好的序列化形式。 - scottb
你提到的可序列化类的目的是什么? - jaco0646
@jaco0646<br> 我现在要讲的这个类是一个Pogo类,并且它实现了可序列化接口。在另一个类中,我们使用不同的服务为Pogo类字段设置一些值。 - Anurag_BEHS
你的项目中使用了RMI吗? - yadab
@yadav,是的,我们正在调用其他服务。 - Anurag_BEHS
7个回答

22

如果对象要离开它所在的JVM,则该类应实现Serializable接口。

序列化是一种方法,可以将对象表示为字节序列,其中包括对象的数据以及有关对象类型和存储在对象中的数据类型的信息。

将序列化对象写入文件后,可以从文件中读取并进行反序列化,即可以使用表示对象及其数据的类型信息和字节来重新创建内存中的对象。

这就是反序列化的主要目的。从一个已经写入(松散地说)表示对象的地方获取对象信息、对象类型、变量类型信息。因此,首先需要序列化才能实现此目的。

因此,每当您的对象有可能离开正在执行程序的JVM时,都应该使该类实现Serializable接口。

将对象读写到文件(内存)中,或通过Internet或任何其他类型的连接传递对象。只要对象离开它所创建的JVM,它就应该实现Serializable接口,以便在返回另一个/同一个JVM时可以进行序列化和反序列化以进行识别。

更多好的阅读资源:


但在我的情况下,没有任何可能对象会离开JVM.......:( - Anurag_BEHS
那么就没有必要实现 Serializable 接口了。 :) 我希望我能解释为什么需要它。 - Samrat Dutta

10

序列化的好处:

  1. 将数据持久化以备将来使用。

  2. 使用客户端/服务器Java技术(如RMI,套接字编程等)将数据发送到远程计算机。

  3. 将对象压缩为内存中的字节数组。

  4. 在群集中的服务器之间发送对象。

  5. 在小应用程序和servlets之间交换数据。

  6. 在Web应用程序中存储用户会话。

  7. 激活/去活企业JavaBean。

您可以参考这篇文章了解更多细节。


6
如果你期望你的对象在RMI环境中被用作数据,那么它们应该是可序列化的,因为RMI需要对象是可序列化的(如果它们要被序列化并发送到远程端)或者是一个UnicastRemoteObject(如果你需要一个远程引用)。

5

在Java 5之前的早期版本中,标记接口是声明元数据的好方法,但现在我们有了注解,它们更强大,可以为类声明元数据。

注解提供了非常灵活和动态的功能,我们可以为注解元数据提供配置,无论是在字节代码中还是在运行时发送该信息。

如果您不想读取和编写对象,则序列化的目的仅剩下一个,即为类声明元数据。如果要为类声明元数据,则个人建议您不要使用序列化,而应使用注解。

注解比标记接口更好的选择,JUnit就是使用注解的完美例子,例如@Test用于指定测试类。同样的效果也可以使用Test标记接口实现。

还有一个例子表明注解是更好的选择@ThreadSafe看起来比实现ThraedSafe标记接口更好。


2

有些情况下,您需要按值而不是按引用发送对象:

  • 通过网络发送对象。

在这里实际上无法通过引用发送对象。

  • 多线程,特别是在Android中

Android使用Serializable/Parcelable在Activity之间发送信息。这与内存映射和多线程有关,但我并不真正理解这个过程。


1
除了 Martin C的回答外,我还想补充一点-如果您使用Serializable,则可以轻松将Object图加载到内存中。例如,您有一个Student类,其中包含一个Deportment。因此,如果您序列化您的Student,那么Department也会被保存。此外,它还允许您 -

1.在保持向后兼容性的同时重命名序列化类中的变量。
2.从新版本中删除的字段中访问数据(换句话说,在保持向后兼容性的同时更改数据的内部表示)。


0

有些框架/环境可能依赖于数据对象的可序列化。例如在J2EE中,HttpSession属性必须是可序列化的,才能从会话持久性中获益。另外,RMI和其他早期的工具也使用序列化。

因此,尽管您可能不需要立即将数据对象设为可序列化,但这样做可能是有意义的,以防万一(除非您需要声明readObject/writeObject方法,否则几乎不需要额外付出代价)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接