我们在IT技术领域中大量使用序列化,需要在每个使用的对象上指定Serializable标签有点繁琐,特别是当它是第三方类,我们无法更改时。
问题是: 既然Serializable是一个空接口,并且Java提供了强大的序列化功能,一旦添加了implements Serializable
为什么他们不把所有东西都做成可序列化呢?
我错过了什么吗?
我们在IT技术领域中大量使用序列化,需要在每个使用的对象上指定Serializable标签有点繁琐,特别是当它是第三方类,我们无法更改时。
问题是: 既然Serializable是一个空接口,并且Java提供了强大的序列化功能,一旦添加了implements Serializable
为什么他们不把所有东西都做成可序列化呢?
我错过了什么吗?
序列化充满了陷阱。这种形式的自动序列化支持使类内部成为公共API的一部分(这就是为什么javadoc会给出类的持久化形式)。
对于长期持久性,类必须能够解码此表单,这限制了您可以对类设计进行的更改。这破坏了封装性。
序列化也可能导致安全问题。通过能够序列化它引用的任何对象,类可以访问它通常无法访问的数据(通过解析生成的字节数据)。
还有其他问题,例如内部类的序列化形式没有明确定义。
使所有类可序列化将加剧这些问题。请查看Effective Java第二版,特别是第74项:审慎实现Serializable。
我认为Java和.Net的人这一次都错了,最好将所有内容默认序列化,并且只需要标记那些不能安全序列化的类。
例如,在70年代创建的Smalltalk语言中,每个对象都是默认可序列化的。考虑到绝大多数对象都可以安全序列化,而只有极少数对象不能安全序列化,我不知道为什么在Java中没有这种情况。
将对象标记为可序列化(使用接口)并不能使该对象神奇地变得可序列化,它本来就是可序列化的,只是现在您表达了系统本来就能够找到的东西,因此我认为目前的序列化方式没有真正充分的理由。
我认为这要么是设计师做出的糟糕决定,要么是序列化被忽视了,或者平台从未准备好在所有对象上默认进行安全、一致的序列化。
并非所有的内容都可以被真正地序列化。以网络套接字连接为例,你可以序列化套接字对象的数据/状态,但是活动连接的本质将会丢失。
implements NotSerializable
:) - Rob Grant序列化会增加约束和潜在问题,因为结构兼容性不能得到保证。默认情况下关闭它会有好处。
我必须承认,我很少见到标准序列化在非平凡类中做到我想要的事情,特别是在复杂数据结构的情况下。因此,为使类正确序列化所花费的精力远远超过添加接口的成本。
对于一些类,特别是那些代表一些更物理的东西,比如文件、套接字、线程或数据库连接,序列化实例是没有任何意义的。对于许多其他类,序列化可能会有问题,因为它破坏了唯一性约束条件,或者强制你处理不同版本的类的实例,这可能不是你想要的。
可以说,最好默认将所有内容设置为可序列化,并通过关键字或标记接口使类不可序列化 - 但是,那些应该使用该选项的人可能不会考虑到这一点。现在,如果你需要实现Serializable,你将会收到一个异常提示。
我认为这样做是为了确保你作为程序员知道你的对象可能会被序列化。
显然,在一些初步的设计中,所有内容都是可序列化的,但由于安全和正确性方面的考虑,最终的设计变成了我们现在所知道的样子。
必须明确声明某个类的实例是可序列化的,这种语言强制你思考是否应该允许。对于简单的值对象,序列化是微不足道的,但在更复杂的情况下,你需要认真思考。
仅依赖于JVM的标准序列化支持将会导致各种令人讨厌的版本问题。
唯一性、对“真实”资源的引用、计时器和许多其他类型的工件都不是序列化的候选对象。
好的,我的答案是这没有什么好的理由。从你的评论中我可以看出你已经了解到了这一点。其他编程语言很高兴地尝试序列化所有在你数到10之后不跳上树的东西。一个对象应该默认为可序列化。
所以,你基本上需要做的就是自己读取第三方类的所有属性。或者,如果这对你来说是个选项:反编译,把该死的关键字放在那里,然后重新编译。