使用可序列化而不是向/从文件写入和读取对象

Posted

技术标签:

【中文标题】使用可序列化而不是向/从文件写入和读取对象【英文标题】:Use of Serializable other than Writing& Reading object to/from File 【发布时间】:2015-10-10 00:40:34 【问题描述】:

在哪些情况下,使用实现可序列化而不是从文件中写入和读取对象是一种很好的编码实践。在一个项目中,我经历了代码。即使在该类/项目中没有任何向/从文件写入/读取对象的类使用实现可序列化?

【问题讨论】:

请注意,实现Serializable 并不像看起来那么简单。它破坏了封装,代表了一种语言外的对象创建机制,并可能导致安全漏洞。它会导致将隐藏的实现细节作为类 API 的一部分导出。对于某些类,必须非常小心才能开发出良好的序列化形式。 你提到的可序列化类的目的是什么? @jaco0646 我所说的类是一个 pogo 类。它的实现可序列化。在不同的类中,我们使用不同的服务在 pogo 类字段中设置一些值。 您的项目中是否使用了 RMI? @yadav..是的,我们正在调用其他服务 【参考方案1】:

如果对象离开创建它的 JVM,则该类应实现 Serializable。

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

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

这是反序列化的主要目的。从对象的书面(松散地说)表示中获取对象信息、对象类型、变量类型信息。因此,首先需要序列化才能使这成为可能。

所以,只要你的对象有可能离开 JVM,程序正在其中执行,你就应该创建类,实现 Serializable。

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

很多不错的读物:

1:Why Java needs Serializable interface? 2:What is the purpose of Serialization in Java?

【讨论】:

但在我的情况下,对象不可能离开 jvm.......:( 那么就不需要实现Serializable接口了。 :) 我希望我能解释为什么需要它。【参考方案2】:

序列化的好处:

    保留数据以备将来使用。

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

    将对象展平为内存中的字节数组。

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

    在 applet 和 servlet 之间交换数据。

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

    激活/钝化企业 Java bean。

您可以参考此article 了解更多详情。

【讨论】:

【参考方案3】:

如果您希望您的对象在 RMI 设置中用作数据,它们应该是可序列化的,因为 RMI 要么需要对象 Serializable(如果它们要被序列化并发送到远程端),要么是UnicastRemoteObject 如果您需要远程参考。

【讨论】:

【参考方案4】:

在 Java 的早期版本(Java 5 之前)中,标记接口是声明元数据的好方法,但目前我们有更强大的注释来为类声明元数据。

注解提供了非常灵活和动态的功能,我们可以为注解元数据提供配置,以便我们希望在字节码或运行时发送该信息。

如果你不愿意读写对象,那么序列化的一个目的是为类声明元数据,如果你要为类声明元数据,那么我个人建议你不要只使用序列化去注释。

Annotation 是比标记接口更好的选择,JUnit 是使用 Annotation 的完美示例,例如@Test 用于指定测试类。使用测试标记接口也可以实现。

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

【讨论】:

【参考方案5】:

在其他情况下,您希望按值而不是按引用发送对象:

通过网络发送对象。

这里不能真正通过引用发送对象。

多线程,尤其是在 android

Android 使用 Serializable/Parcelable 在活动之间发送信息。它与内存映射和多线程有关。不过我不是很明白。

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

某些框架/环境可能依赖于可序列化的数据对象。例如,在 J2EE 中,HttpSession 属性必须是可序列化的,才能从 Session Persistence 中受益。 RMI 和其他 dark ages artifacts 也使用序列化。

因此,尽管您可能不需要立即将数据对象序列化,但声明 Serializable 以防万一(它几乎是免费的,除非您需要经历声明readObject/writeObject methods)

【讨论】:

以上是关于使用可序列化而不是向/从文件写入和读取对象的主要内容,如果未能解决你的问题,请参考以下文章

C语言复习之直接向文件中写入和读取时间Date对象

I/O

序列化流与反序列化流

向/从映射文件 C++ 写入和读取

Hadoop HDFS:读取正在写入的序列文件

fs.writeFile() 在关闭脚本时写入 [object, object] 而不是实际的对象