Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle a Findbugs "Non-transient non-serializable instance field in serializable class"?

Consider the class below. If I run Findbugs against it it will give me an error ("Non-transient non-serializable instance field in serializable class") on line 5 but not on line 7.

1 public class TestClass implements Serializable { 2 3  private static final long serialVersionUID = 1905162041950251407L; 4 5  private Set<Integer> mySet;      // Findbugs error 6 7  private HashSet<Integer> myOtherSet; 8 9 } 

That's correct because java.util.Set never implements Serializable in its hierarchy and java.util.HashSet does. However it is best practice to code against interfaces instead of concrete implementations.

How can I best handle this?

I can add a @Suppresswarnings(justification="No bug", values="SE_BAD_FIELD") on line 3. I have quite a lot of Sets and Lists in my actual code and I'm afraid it will litter my code too much.

Are there better ways?

like image 307
Koohoolinn Avatar asked Feb 01 '11 10:02

Koohoolinn


People also ask

Can a serializable class contains a non serializable field in Java?

the non-serializable field's Class must have an API to allow getting it's state (for writing to the object stream) and then instantiating a new instance with that state (when later reading from the object stream.)

Is serializable consider declaring a serialVersionUID?

However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during ...

Is transient not set by Deserialization?

"Transient field that isn't set by deserialization." is shown when the class implements Externalizable but its super implements Serializable. Field that marked as transient are pointed out as not deserialized although it's in readExternal.

What is serializable interface in Java?

The Serializable interface is present in java.io package. It is a marker interface. A Marker Interface does not have any methods and fields. Thus classes implementing it do not have to implement any methods. Classes implement it if they want their instances to be Serialized or Deserialized.


2 Answers

However it is best practice to code against interfaces instead of concrete implementations.

I submit that no, in this case it is not. Findbugs quite correctly tells you that you risk running into a NotSerializableException as soon as you have a non-serializable Set implementation in that field. This is something you should deal with. How, that depends on the design of your classes.

  • If those collections are initialized within the class and never set from outside, then I see absolutely nothing wrong with declaring the concrete type for the field, since fields are implementation details anyway. Do use the interface type in the public interface.
  • If the collection are passed into the class via a public interface, you have to ensure that they are in fact Serializable. To do that, create an interface SerializableSet extends Set, Serializable and use it for your field. Then, either:
    • Use SerializableSet in the public interface and provide implementation classes that implement it.
    • Check collections passed to the class via instanceof Serializable and if they're not, copy them into something that is.
like image 155
Michael Borgwardt Avatar answered Sep 19 '22 16:09

Michael Borgwardt


I know this is an old question that's already answered but just so others know is that you can set the Set<Integer> field as transient if you have no interest in serializing that particular field which will fix your FindBugs error.

public class TestClass implements Serializable {      private static final long serialVersionUID = 1905162041950251407L;     private transient Set<Integer> mySet;  } 

I prefer this method instead of forcing users of your API to cast to your concrete type, unless it's just internal, then Michael Borgwardt's answer makes more sense.

like image 36
Graham Avatar answered Sep 16 '22 16:09

Graham