1

If I have classes:

class NonSerializable {
}

class CanSerialize implements Serializable {
    private static final long serialVersionUID = 0L;
    public NonSerializable nonSerializable;
}

FindBugs raises violation

<BugInstance rank="14" category="BAD_PRACTICE" priority="1" abbrev="Se" type="SE_BAD_FIELD">

and this looks correct.

However, when I change the code to be:

class NonSerializable {
}

enum CanSerialize {
    INSTANCE;
    public NonSerializable nonSerializable;
}

FindBugs doesn't complain anymore. Is it bug in FindBugs or it's safe to have non-transient, non-serializable fields in enums?

Michal Kordas
  • 10,475
  • 7
  • 58
  • 103
  • Just for the record; why do you need `Serializable`? – fge Aug 29 '16 at 10:10
  • @fge I don't need, but every enum in Java is by default `Serializable` – Michal Kordas Aug 29 '16 at 10:22
  • 2
    As I understand the top answer to [Is custom enum Serializable too?](http://stackoverflow.com/questions/15521309/is-custom-enum-serializable-too), your field is not being serialized when the enum is. If I have understood that correctly, there’s no need for `nonSerializable` to be serializable. – Ole V.V. Aug 29 '16 at 10:30
  • @OleV.V. You are right! Consider posting that as an answer. :-) – barfuin Sep 25 '16 at 11:56

1 Answers1

2

On one hand, the answer to your question is it’s safe to have non-transient non-serializable fields in an enum. On the other, they don’t get serialized when the enum does. So even if they are not declared transient, they work sonewhat like transient fields nevertheless.

From the Java Object Serialization Specification:

1.12 Serialization of Enum Constants Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream.

(http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/serial-arch.html#enum)

So whether NonSerializable was serializable or not wouldn’t really make a difference. So FindBugs is correct in not flagging this in an enum.

If I may guess, fields in an enum are very often effectively final and initialized when the enum is loaded by the classloader, so maybe they figured that there was no point in serializing them, they can be just as well initialized again next time the enum is loaded by the classloader. It’s not something I know.

Edit: With thanks to @TJR for the link, the following SpotBugs issue is related (and links to your question): False positive SE_BAD_FIELD for non-transient non-serializable in an enum. SpotBugs is the successor of FindBugs built on the FindBugs code base and further developed.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 2
    The annoying thing here is that findbugs actually does flag these... even though it would be correct in not doing so. At least, it does in some versions. – Christopher Aug 28 '18 at 02:15