我有一个问题,因为我有点困惑(或者我可能没注意到一些明显的东西)。假设我有一些包含很多类的源代码,这些类包含大量像这样定义的静态字段:
public final class ConverterTYPE {
private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>() {
{
put("A", new Byte((byte)12));
put("B", new Byte((byte)13));
}
};
}
众所周知,静态字段不会被序列化。
然而,Java(和Eclipse)抱怨“可序列化类没有声明类型为long的静态最终serialVersionUID字段”。为什么他们不能注意到静态不会被序列化?
接下来的问题:使用@SuppressWarnings("serial")
摆脱所有此类警告,这个问题是否正确?
修改
我的类都没有实现Serializable接口(或者没有超类)。 Eclipse指出HashMap<String, Byte>
的警告。为什么不检测到它是静态场?
答案 0 :(得分:22)
仅仅因为该字段可能未被序列化并不意味着它引用的东西本身永远不会被序列化!有人/其他东西可以获得对该映射的引用并尝试直接序列化它,或者将其用作可序列化类中的实例成员等。我看到它是私有的,但确保它永远不会在当前类之外访问或者设置为实例成员超出了编译器的范围(无论如何都不可能反射)。
一种可能的解决方案是简单地避免将匿名子类与初始化器样式放在一起并执行此操作:
private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>();
static {
STRING_MAP.put("A", new Byte((byte)12));
STRING_MAP.put("B", new Byte((byte)13));
}
在大多数情况下,结果几乎相同,并且您的代码不会使用匿名类。
答案 1 :(得分:19)
然而,Java(和Eclipse)抱怨“可序列化类没有声明类型为long的静态最终serialVersionUID字段”。为什么他们不能注意到静态不会被序列化?
错误消息以及您的班级中有最终静态成员变量的事实(至少,我是如何解释您的描述)彼此之间没有任何关系。
您的类实现了接口Serializable
,或者您的类的一个超类实现了这一点。因此编译器注意到您的类是可序列化的。可序列化类应该有一个名为serialVersionUID
的静态最终字段,用于在序列化类的实例时进行版本控制。
使用注释@SuppressWarnings("serial")
会使编译器因缺少serialVersionUID
而关闭。所以,是的,您可以使用它来消除警告消息,但更好的解决方案是让您的类不实现Serializable
(直接或间接),如果它不是要序列化的。