FindBugs 不抱怨枚举中的不可序列化字段

FindBugs not complaining on non-serializable fields in enums

如果我有类:

class NonSerializable {
}

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

FindBugs 提出违规

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

这看起来是正确的。

但是,当我将代码更改为:

class NonSerializable {
}

enum CanSerialize {
    INSTANCE;
    public NonSerializable nonSerializable;
}

FindBugs 不再抱怨了。它是 FindBugs 中的错误还是在枚举中具有非瞬态、不可序列化的字段是安全的?

一方面,您问题的答案是在枚举中拥有非瞬态不可序列化字段是安全的。另一方面,当枚举序列化时,它们不会被序列化。因此,即使它们没有被声明为瞬态,它们的工作方式仍然有点像瞬态场。

来自 Java 对象序列化规范:

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)

所以 NonSerializable 是否可序列化并没有什么区别。所以 FindBugs 没有在枚举中标记它是正确的。

如果我猜的话,枚举中的字段通常在类加载器加载枚举时有效地最终和初始化,所以也许他们认为序列化它们没有意义,它们也可以被初始化下次枚举由类加载器加载时再次。这不是我知道的。

编辑: 感谢@TJR 的 link,以下 SpotBugs 问题是相关的(并且 links 与您的问题相关):False positive SE_BAD_FIELD for non-transient non-serializable in an enum。 SpotBugs 是 FindBugs 的继任者,它建立在 FindBugs 代码库之上并进一步发展。