FindBugs wants readObject(…) to be private for serialization, why?

后端 未结 5 1995
太阳男子
太阳男子 2021-01-20 08:59

I am running findbugs on some code and it says the readObject(...) method must be private to be invoked for serialization/unserialization? Why? What is the problem if it is

相关标签:
5条回答
  • 2021-01-20 09:34

    In the modern Java implementations (at least JDK 6 through 10), the ObjectInputStream and ObjectOutputStream classes will only recognize readObject, readObjectNoData and writeObject methods if they are declared as private and NOT static.

    (I couldn't find this stated explicitly in any of the documentation, but the restriction is clearly implemented in the code.)

    So, irrespective of whether it is a good idea or not, FindBugs is correct in pointing out that a non-private readObject method is a bug. It won't be used.

    The only reason I want to make this method public is to make it final so that inheriting objects cannot fiddle with it.

    I don't think you should try to do that. Put a note in the class-level javadoc to say what you think that subclasses should and should not do. If someone chooses to implement a class ignoring that advice, it is their problem to deal with the consequences.

    The problem with trying to force other people to implement subclasses in a particular way is that they may have a use-case that requires them to do things differently ... for reasons that you are not in a position to understand. It is a better idea to leave future developers with the freedom to do what they want, and let them take responsibility for the consequences.

    0 讨论(0)
  • 2021-01-20 09:40

    There's no reason for you to call serialization methods such as readObject yourself, much less from another class. You should minimize the visibility of everything you can.

    Edit: If you want subclasses to be able to change the behavior, make the method protected... that's acceptable.

    0 讨论(0)
  • 2021-01-20 09:40

    In order for your method to be called by objectInputStream.readObject(), you must declare it private:

    private void readObject(ObjectInputStream objectInputStream)
    

    If you do not, your method will not be called (put a break point in there to prove this). Your code may appear to work but that is because the default serialization is being used.

    You might be wanting to make this protected to allow for subclassing but this is not needed. The serialization process automatically calls the readObject of the base class prior to calling the readObject of the concrete class. This happens even if the concrete class does not make a call to:

    objectInputStream.defaultReadObject();
    

    ...contrary to other posts I have read on the web. The same applies to the writeObject methods as well.

    0 讨论(0)
  • 2021-01-20 09:55

    I'm not sure why findbugs thinks it's a bug, but I can guess at two possible reasons. Making readObject public breaks encapsulation because the calling code has visibility into the internal structure of your class. Also, by making it public you force all derived classes to declare readObject as public. So unless the class is final, you're changing the contract for serialization.

    I thought findbugs could provide rationale for most of its messages. Does it have anything to say about this?

    0 讨论(0)
  • 2021-01-20 09:56

    About readObject()/writeObject() being private, here's the deal: if your class Bar extends some class Foo; Foo also implements readObject()/writeObject() and Bar also implements readObject()/writeObject().

    Now, when a Bar object is serialized or deserialized, JVM needs to call readObject()/writeObject() for both Foo and Bar automatically (i.e. without you needing to call these super class methods explicitly). However, if these methods are anything but private, it becomes method overriding, and JVM can no longer call the super class methods on the sub class object.

    Hence they must be private!

    0 讨论(0)
提交回复
热议问题