为什么java.lang.Object没有实现Serializable接口?

37

可能是重复问题:
为什么Java需要Serializable接口?

根据Java文档中的序列化性:

类的序列化由类实现java.io.Serializable接口启用。没有实现此接口的类将不会被序列化或反序列化。可序列化类的所有子类型本身也是可序列化的。序列化接口没有方法或字段,只用于标识可序列化的语义。

为什么Object没有默认实现Serializable?我们可能希望不想序列化的成员可以被设置为transient。为什么要防止默认的序列化性?


2
这个问题包含了一些不错的答案,可能会引起你的兴趣。 - Pshemo
确实,我在发布之前应该尝试其他关键词 :) - TJ-
4个回答

47

潜在的安全漏洞

所有可序列化类的子类型本身也是可序列化的。

换句话说:您创建、曾经创建或将要创建的所有类都是可序列化的,transient只会排除字段而不是整个类。

这是一个潜在的安全漏洞 - 可能会碰巧序列化带有数据库凭据的DataSource,如果该特定DataSource实现的创建者忘记使这些字段变为transient。很容易通过持有对外部this的隐式引用的内部类来序列化任意Java对象。

相比于仔细检查您的代码并确保从未序列化任何不需要的字段,使用白名单明确允许序列化的类更加安全。

此外,您不能再说:MySuperSecretClass不可序列化(通过简单地不实现Serializable)- 您只能排除其内容(字段)。


1
好的,我想我完全忽略了它的安全性方面。有道理。但是我们不是使用Private/Public/Protected来进行编译时访问控制吗?不能将transient或类似的东西作为运行时强制要求吗?只是问问而已。或者这会变得很麻烦。 - TJ-
4
在我看来,只有很少一部分类需要可序列化(值对象、DTO)。标记需要可序列化的类比标记不需要可序列化的类更为方便。尽管在这方面Java有些麻烦:在我看来,所有的字段应该默认为私有,所有的方法应该默认为公有,但是你能做什么呢? - Tomasz Nurkiewicz

18

1. Serializable是一个标记接口,它是空的,但当一个类被标记为Serializable时,它的对象就可以进行序列化。

2. java.lang.Object 没有实现 Serializable 是因为,如果您不想将某些字段标记为 Serializable 并且您错误地忘记将该字段添加为 transient,那么会造成混乱。

3. 通过使程序员为他的类实现 Serializable 接口,它使程序员意识到他已经有意识地实现了它,并且应该采取必要的步骤来防止序列化任何不应该被序列化的内容。


5

大多数类不需要被序列化。通过当前的设计,您可以轻松地注意到该类是可序列化的。本质上,它只是经过编译器检查的自我文档化。否则,您可能会写出以下内容:

/** DON'T SERIALIZE IT!!! */
class Connection { ... }

最好拥有语言或库的功能,而不是注释。


1

我认为对于需要持久化的对象来说,实现Serializable更有意义,而将类的每个字段声明为transient会更加繁琐。另一个我不确定的点是,Object是所有类的根,包括反射相关的类,因此为Object类实现Serializable是不合适的。


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