您使用的语法称为双括号初始化 http://www.c2.com/cgi/wiki?DoubleBraceInitialization- 这实际上是一个“实例初始化块 http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html这是一个匿名内部类 http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html“(当然不是黑客)。所以,当使用这种表示法时,您实际上是在定义一个新类(!)。
你的情况的“问题”是HashMap http://java.sun.com/javase/6/docs/api/java/util/HashMap.html实施Serializable http://java.sun.com/javase/6/docs/api/java/io/Serializable.html。该接口没有任何方法并且仅用于识别可序列化的语义。换句话说,它是一个标记接口,您实际上不需要实现任何东西。But,在反序列化过程中,Java 使用一个称为serialVersionUID
验证序列化版本是否与目标兼容。如果你不提供这个serialVersionUID
,就会被计算出来。并且,如 javadoc 中所述Serializable http://java.sun.com/javase/6/docs/api/java/io/Serializable.html,计算出的值非常敏感,因此建议显式声明它以避免任何反序列化问题。这就是 Eclipse 所“抱怨”的(注意,这只是一个警告)。
因此,为了避免出现此警告,您可以添加serialVersionUID
到你的匿名内部类:
someMethodThatTakesAHashMap(new HashMap<String, String>() {
private static final long serialVersionUID = -1113582265865921787L;
{
put("a", "value-a");
put("c", "value-c");
}
});
但是你失去了语法的简洁性(你甚至可能不需要它)。
因此,另一种选择是通过添加一个来忽略警告@SuppressWarnings("serial")
到你调用的方法someMethodThatTakesAHashMap(Map)
。这似乎更适合您的情况。
总而言之,虽然这种语法很简洁,但它有一些缺点。首先,如果您持有使用双括号初始化初始化的对象的引用,则隐式持有对不符合垃圾回收条件的外部对象的引用。所以要小心。其次(这听起来像是微优化),双括号初始化有一个非常小的开销 https://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization/924326#924326。第三,正如我们所见,这种技术实际上使用了匿名内部类,因此占用了一些永久代空间(但我怀疑这确实是一个问题,除非你really虐待他们)。最后 - 这可能是最重要的一点 - 我不确定它会使代码更具可读性(这不是众所周知的语法)。
因此,虽然我喜欢在测试中使用它(为了简洁),但我倾向于避免在“常规”代码中使用它。