为什么Java需要Serializable接口?

时间:2009-01-13 22:55:28

标签: java serialization

我们大量使用序列化,并且必须在我们使用的每个对象上指定Serializable标记是一种负担。特别是当它是第三方课程时,我们无法真正改变。

问题是:由于Serializable是一个空接口,一旦你添加implements Serializable,Java就会提供强大的序列化 - 为什么它们不能使所有序列化都可以进行,那就是它?

我错过了什么?

13 个答案:

答案 0 :(得分:114)

序列化充满了陷阱。此表单的自动序列化支持使类内部成为公共API的一部分(这就是为什么javadoc为您提供persisted forms of classes)。

对于长期持久性,类必须能够解码此表单,这限制了您可以对类设计进行的更改。这破坏了封装。

序列化也可能导致安全问题。通过能够序列化它有引用的任何对象,类可以访问通常无法访问的数据(通过解析结果字节数据)。

还有其他问题,例如内部类的序列化形式没有很好地定义。

使所有类可序列化会加剧这些问题。查看Effective Java Second Edition,特别是项目74:明智地实施Serializable

答案 1 :(得分:31)

我认为这次Java和.Net人都错了,最好在默认情况下将所有内容都序列化,只需要标记那些无法安全序列化的类。

例如,在Smalltalk(70年代创建的语言)中,默认情况下每个对象都是可序列化的。我不知道为什么在Java中不是这种情况,考虑到绝大多数对象可以安全地序列化,而其中只有少数不是。

将一个对象标记为可序列化(带有一个接口)并没有神奇地使该对象可序列化,它一直可序列化,只是现在你表达了系统可能在他的上找到的东西拥有,所以我认为序列化没有真正的理由,就像现在这样。

我认为设计师或序列化做出的糟糕决定是事后的想法,或者平台从未准备好在所有对象上默认安全地进行序列化。

答案 2 :(得分:20)

并非所有东西都是真正可序列化的。例如,采用网络套接字连接。您可以序列化套接字对象的数据/状态,但活动连接的本质将会丢失。

答案 3 :(得分:13)

Serializable在Java中的主要作用是默认情况下实现所有其他非可序列化的对象。序列化是一种非常危险的机制,尤其是在其默认实现中。因此,就像C ++中的友谊一样,默认情况下它是关闭的,即使它可以使一些东西可以序列化。

序列化增加了约束和潜在问题,因为结构兼容性没有保证。它默认是关闭的。

我必须承认,我已经看到很少的非平凡类,标准序列化可以实现我想要的。特别是在复杂数据结构的情况下。因此,您需要花费大量时间才能使类序列化,这使得添加接口的成本相形见绌。

答案 4 :(得分:9)

对于某些类,特别是那些表示更像物理内容的类,如文件,套接字,线程或数据库连接,序列化实例绝对没有意义。对于许多其他人来说,序列化可能会有问题,因为它会破坏唯一性约束,或者只是强迫您处理类的不同版本的实例,这可能是您不想要的。

可以说,最好在默认情况下使所有Seri​​alizable和通过关键字或标记接口使类不可序列化 - 但是那些应该使用该选项的人可能不会考虑它。就这样,如果你需要实现Serializable,你会被异常告诉你。

答案 5 :(得分:4)

我认为这是为了确保你作为程序员知道你的对象是我的序列化。

答案 6 :(得分:3)

显然,在一些初步设计中,所有内容都是可序列化的,但由于安全性和正确性,我们都知道最终的设计结束了。

来源:Why must classes implement Serializable in order to be written to an ObjectOutputStream?

答案 7 :(得分:1)

必须明确说明某个类的实例是Serializable,语言会强迫您考虑是否应该允许它。对于简单的值对象,序列化是微不足道的,但在更复杂的情况下,您需要真正思考问题。

只需依靠JVM的标准序列化支持,您就会面临各种令人讨厌的版本问题。

唯一性,对“真实”资源,计时器和许多其他类型工件的引用不是序列化的候选者。

答案 8 :(得分:1)

阅读本章以了解Serializable Interface以及为什么我们应该只生成少数类Serializable,并且我们还要考虑使用transient关键字,以防我们想要从存储过程中删除少量字段。

http://www.codingeek.com/java/io/object-streams-serialization-deserialization-java-example-serializable-interface/

答案 9 :(得分:0)

嗯,我的回答是,这是没有充分理由的。从你的评论我可以看出你已经学到了这一点。其他语言愉快地尝试序列化在计数到10之后不会跳到树上的所有内容。对象应默认为可序列化。

因此,您基本上需要做的是自己阅读第三方课程的所有属性。或者,如果这是你的选择:反编译,将该死的关键字放在那里,然后重新编译。

答案 10 :(得分:0)

Java中有些东西根本无法做到 被序列化,因为它们是特定于运行时的。像流,线程,运行时, 甚至一些GUI类(连接到底层OS)也不行 被序列化。

答案 11 :(得分:0)

虽然我同意其他答案中的观点,但真正的问题在于反序列化:如果类定义发生变化,那么反序列化将无法正常运行。永远不要修改现有字段是图书馆作者的一个非常重要的承诺!保持API兼容性就足够了。

答案 12 :(得分:0)

需要持久保存到文件或其他媒体的类必须实现Serializable接口,以便JVM可以允许类对象被序列化。 为什么Object类没有被序列化,所以没有类需要实现接口,只有当我使用 ObjectOutputStream 时,所有JVM序列化类,这意味着控件仍然在我手中让JVM序列化

由于类版本是主要问题,因此默认情况下Object类不可序列化的原因。因此,对序列化感兴趣的每个类都必须明确标记为Serializable,并提供版本号serialVersionUID。

如果未提供 serialVersionUID ,则在反序列化对象时会出现意外结果,这就是为什么JVM会抛出 InvalidClassException ,如果 serialVersionUID 没有&#39 ;匹配。因此,每个类都必须实现 Serializable 接口并提供 serialVersionUID 以确保两端提供的Class相同。