我们需要大量的序列化工作,并且必须在使用的每个对象上指定Serializable标签,这是一种负担。特别是当它是第三方类时,我们无法真正更改。
问题是:由于Serializable是一个空接口,并且Java一旦添加便提供了可靠的序列化 implements Serializable
-为什么它们不使所有内容都可序列化,仅此而已?
我想念什么?
我们需要大量的序列化工作,并且必须在使用的每个对象上指定Serializable标签,这是一种负担。特别是当它是第三方类时,我们无法真正更改。
问题是:由于Serializable是一个空接口,并且Java一旦添加便提供了可靠的序列化 implements Serializable
-为什么它们不使所有内容都可序列化,仅此而已?
我想念什么?
Answers:
序列化充满陷阱。这种形式的自动序列化支持使类内部成为公共API的一部分(这就是javadoc为您提供类的持久形式的原因)。
为了实现长期持久性,类必须能够解码这种形式,这限制了您可以对类设计进行的更改。这破坏了封装。
序列化也可能导致安全问题。通过能够序列化其引用的任何对象,类可以访问它通常无法访问的数据(通过解析结果字节数据)。
还有其他问题,例如内部类的序列化形式定义不正确。
使所有类都可序列化会加剧这些问题。请查看有效的Java第二版,特别是项目74:明智地实现可序列化。
我认为Java和.Net人士这次都错了,最好将所有内容默认设置为可序列化,而只需要标记那些不能安全地序列化的类即可。
例如,在Smalltalk(70年代创建的语言)中,每个对象默认情况下都可以序列化。考虑到绝大多数对象都可以安全地序列化,而只有少数对象不是,因此我不知道Java中为什么不是这种情况。
将对象标记为可序列化(带有接口)并不能使该对象可序列化,它一直都是可序列化的,只是现在您表达了系统可以自己发现的东西,所以我认为没有真正的理由序列化就是现在的样子。
我认为这要么是设计人员做出的错误决定,要么是事后才想到序列化,或者默认情况下该平台从未准备好安全,一致地对所有对象进行序列化。
Serializable
技巧只是十年或两年前做出的另一个错误决定,并且是处理纯Java时烦恼的又一个补充,例如标准库中集合和字符串处理中的一些缺陷。令人高兴的是有Kryo,但这是依赖关系,需要首先找到它。这就是应该完成内置序列化的方式。
并非所有内容都是真正可序列化的。以网络套接字连接为例。您可以序列化套接字对象的数据/状态,但是活动连接的本质将丢失。
implements NotSerializable
:)
显然,在某些初步设计中,所有内容都可以序列化,但是由于安全性和正确性的关系,最终设计最终众所周知。
阅读此书以了解Serializable接口以及为什么我们只应使几个类可序列化,并且在要从存储过程中删除一些字段的情况下,我们也应注意在哪里使用transient关键字。
Java中有些东西根本无法序列化,因为它们是运行时特定的。流,线程,运行时等内容,甚至某些GUI类(连接到底层OS)都无法序列化。
需要持久化到文件或其他媒体上的类必须实现Serializable接口,以便JVM可以允许对类对象进行序列化。为什么不对Object类进行序列化,那么所有类都无需实现接口,毕竟只有当我使用ObjectOutputStream时,所有JVM才会对类进行序列化,这意味着控件仍在我手中,可以让JVM对序列化。
对象类默认情况下无法序列化的原因是该类版本是主要问题。因此,每个对序列化感兴趣的类都必须显式标记为Serializable并提供版本号serialVersionUID。
如果未提供serialVersionUID,则在反序列化对象时会得到意外结果,这就是为什么如果serialVersionUID 不匹配,JVM会抛出InvalidClassException的原因。因此,每个类都必须实现Serializable接口,并提供serialVersionUID以确保两端显示的类相同。