FindBugs希望readObject(...)是私有的序列化,为什么?

时间:2011-08-12 01:27:49

标签: java serialization findbugs

我在一些代码上运行findbugs并且它说readObject(...)方法必须是私有的才能被调用以进行序列化/反序列化?为什么?如果将其公开,会出现什么问题?

5 个答案:

答案 0 :(得分:6)

关于readObject()/writeObject()私有,这是交易:如果你的班级延伸了一些类Foo; Foo还实现了readObject()/writeObject(),Bar也实现了readObject()/writeObject()

现在,当一个Bar对象被序列化或反序列化时,JVM需要自动为Foo和Bar调用readObject()/writeObject()(即,不需要显式调用这些超类方法)。但是,如果这些方法不是私有的,那么它将成为方法重写,并且JVM不能再调用子类对象上的超类方法。

因此他们必须是私人的!

答案 1 :(得分:3)

在现代Java实现中(至少JDK 6到10),ObjectInputStreamObjectOutputStream类只能识别readObjectreadObjectNoDatawriteObject方法,如果它们被声明为private而非static

(我在任何文档中都没有明确说明这一点,但是在代码中明确地实现了限制。)

因此,无论是否是一个好主意,FindBugs都指出非私有readObject方法是一个错误。它不会被使用。

  

我想让这个方法公开的唯一原因是让它成为最终的,这样继承对象就无法摆弄它。

我认为你不应该尝试来做到这一点。在类级别的javadoc中添加一个注释,说明您认为子类应该和不应该做什么。如果有人选择实施忽略该建议的课程,那么处理后果是他们的问题。

试图强迫其他人以特定方式实现子类的问题在于,他们可能有一个用例要求他们以不同方式执行操作...原因是你不是能够理解。让未来的开发人员自由地做他们想做的事情是一个更好的主意,让他们对后果承担责任。

答案 2 :(得分:1)

我不确定为什么findbugs认为这是一个错误,但我猜可能有两个原因。使readObject公开打破封装,因为调用代码可以看到类的内部结构。此外,通过将其公开,您强制所有派生类将readObject声明为public。因此,除非该类是最终的,否则您将更改序列化合同。

我认为findbugs可以为其大部分消息提供理由。这有什么可说的吗?

答案 3 :(得分:1)

您没有理由自己调用readObject等序列化方法,更不用说来自另一个类了。你应该尽可能减少所有事情的可见度。

编辑:如果您希望子类能够更改行为,请创建方法protected ......这是可以接受的。

答案 4 :(得分:1)

为了让objectInputStream.readObject()调用您的方法,您必须将其声明为private:

private void readObject(ObjectInputStream objectInputStream)

如果你不这样做,你的方法将不会被调用(在那里设置一个断点来证明这一点)。您的代码似乎可以正常工作,但这是因为正在使用默认序列化。

您可能希望对此进行保护以允许子类化,但这不是必需的。序列化过程在调用具体类的readObject之前自动调用基类的readObject。即使具体类没有调用:

,也会发生这种情况
objectInputStream.defaultReadObject();

...与我在网上看过的其他帖子相反。这同样适用于writeObject方法。