如果我有课程:
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中的错误还是在枚举中具有非瞬态,不可序列化的字段是安全的?
答案 0 :(得分:2)
一方面,您的问题的答案是在枚举中安装非瞬态非序列化字段是安全的。另一方面,它们在枚举时不会被序列化。因此,即使它们没有被声明为瞬态,它们也会像瞬态场一样工作。
来自Java对象序列化规范:
1.12枚举常量的序列化 枚举常量的序列化与普通的可序列化或可外部化的对象不同。该 枚举常量的序列化形式仅由其名称组成;领域 常量的值不在表格中。序列化 枚举常量,ObjectOutputStream写入返回的值 枚举常量的名称方法。要反序列化枚举常量, ObjectInputStream从流中读取常量名称;该 然后通过调用,获得反序列化的常量 java.lang.Enum.valueOf方法,传递常量的枚举类型 将收到的常量名称作为参数。像其他可序列化的 或可外部化的对象,枚举常量可以作为目标 随后出现在序列化流中的后向引用。
(http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/serial-arch.html#enum)
因此,NonSerializable
是否可序列化并不会产生任何影响。因此,FindBugs在枚举中不标记这一点是正确的。
如果我猜测,枚举中的字段通常是最终的并且在类加载器加载枚举时初始化,所以也许他们认为序列化它们没有意义,它们可以再次初始化枚举器加载枚举的时间。这不是我所知道的。