我有一些静态初始化代码:
someMethodThatTakesAHashMap(new HashMap<K, V>() {
{
put("a","value-a");
put("c","value-c");}
});
由于某种原因,我收到了来自 Eclipse 的警告: 可序列化类未声明静态最终 serialVersionUID。
这是在提示匿名类吗?我能做些什么呢,或者我应该压制它。
最佳答案
您使用的语法称为 double-brace initialization - 这实际上是一个“instance initialization block 是 anonymous inner class 的一部分”(当然不是黑客)。所以,当使用这个符号时,你实际上是在定义一个新的类(!)。
在您的情况下,“问题”是 HashMap
实现 Serializable
.此接口(interface)没有任何方法,仅用于识别可序列化的语义。换句话说,它是一个标记接口(interface),您实际上不需要实现任何东西。 但是,在反序列化过程中,Java 使用称为 serialVersionUID
的版本号来验证序列化版本是否与目标兼容。如果您不提供此serialVersionUID
,则会进行计算。并且,如 Serializable
的 javadoc 中所述,计算值非常敏感,因此建议明确声明它以避免任何反序列化问题。这就是 Eclipse 所“提示”的内容(请注意,这只是一个警告)。
因此,为避免此警告,您可以在匿名内部类中添加 serialVersionUID
:
someMethodThatTakesAHashMap(new HashMap<String, String>() {
private static final long serialVersionUID = -1113582265865921787L;
{
put("a", "value-a");
put("c", "value-c");
}
});
但是你失去了语法的简洁性(你甚至可能不需要它)。
因此,另一种选择是通过在调用 someMethodThatTakesAHashMap(Map)
的方法中添加 @SuppressWarnings("serial")
来忽略警告。这似乎更适合您的情况。
总而言之,虽然这种语法简洁,但它也有一些缺点。首先,如果您持有对使用双括号初始化初始化的对象的引用,则您隐含地持有对不符合垃圾回收条件的外部对象的引用。所以要小心。其次(这听起来像是微优化),双括号初始化有一个 very a little bit of overhead .第三,正如我们所见,这种技术实际上使用了匿名内部类,因此占用了一些 permgen 空间(但我怀疑这真的是一个问题,除非你真的滥用它们)。最后——这可能是最重要的一点——我不确定它是否使代码更具可读性(这不是众所周知的语法)。
所以,虽然我喜欢在测试中使用它(为了简洁起见),但我倾向于避免在“常规”代码中使用它。
关于java - 了解此警告 : The serializable class does not declare a static final serialVersionUID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1514881/