我有一些静态初始化器代码:

someMethodThatTakesAHashMap(new HashMap<K, V>() {
{
  put("a","value-a"); 
  put("c","value-c");}
});

由于某种原因,我正在收到Eclipse的警告:可序列化类并未声明静态的最终序列化uID。

这是在抱怨匿名课程吗?我该怎么办,或者我应该抑制它。

有帮助吗?

解决方案

您正在使用的语法称为 双臂初始化 - 实际上是实例初始化块 那是一个 匿名内部类“(当然不是黑客)。因此,使用此符号时,您实际上是在定义新类(!)。

在您的情况下,“问题”是 HashMap 工具 Serializable. 。此接口没有任何方法, 仅供识别可序列化的语义. 。换句话说,这是一个标记界面,您不必实现任何东西。 , ,期间,Java使用称为A的版本号 serialVersionUID 验证序列化版本是否与目标兼容。如果您不提供这个 serialVersionUID, ,将计算。并且,如在Javadoc的Javadoc所记录 Serializable, ,计算的值非常敏感,因此建议明确声明它以避免任何挑选问题。这就是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). 。就您而言,这似乎更合适。

这就是说,尽管这种语法简洁,但它有一些缺点。首先,如果您使用双撑架初始化对对象进行了参考,则隐式地保存对不符合垃圾收集资格的外部对象的引用。所以要小心。第二(尽管这听起来像是微型优化),双扶手初始化具有 一点点开销. 。第三,这项技术实际上是我们所看到的匿名内部类,从而吃了一些permgen空间(但我怀疑这确实是一个问题,除非您 真的 虐待他们)。最后 - 这也许是最重要的一点 - 我不确定它使代码更可读(这不是一个知名的语法)。

因此,尽管我喜欢在测试中使用它(为了简洁),但我倾向于避免在“常规”代码中使用它。

其他提示

是的,您可以抑制警告,但是我会这样重写:

HashMap<String, String> map  = new HashMap<String, String>();
map.put("a","value-a"); 
map.put("c","value-c");
someMethodThatTakesAHashMap(map);

不需要抑制,读书也更好,IMO。

我通常同意Bart K.,但出于信息目的:
也可以通过添加字段来消除警告,可以通过击中CTRL+1自动生成。
在定义之前,还可以添加@suppresswarnings(“序列”)注释来抑制警告。
匿名类实现可序列化的实现,并且可序列化需要此静态字段,以便在序列化和去除序列化时可以区分版本。更多信息在这里:
http://www.javablogging.com/what-is-serialversionuid/

ImmutableMap Google Collections库的课程对这种情况很有用。例如

someMethodThatTakesAHashMap(ImmutableMap.<K, V>builder().put("a","value-a").put("c","value-c").build());

或者

someMethodThatTakesAHashMap(ImmutableMap.of("a","value-a","c","value-c"));

要解决您的问题的另一半,“我应该抑制它吗?” - -

是的。我认为,这是一个可怕的警告。默认情况下应 不是 被使用,而不是相反。

如果您不添加serialversionuid,则发生的最糟糕的事情是,实际上与序列化兼容的对象的两个版本被认为是不兼容的。 SerialVersionuID是宣布序列化兼容性没有改变的一种方式,从而覆盖了Java的默认评估。

使用serialversionuid,发生的最糟糕的事情是,当类的序列化形式以不兼容的方式变化时,您会无意中无法更新ID。充其量,您还会遇到运行时错误。在最坏的情况下,情况更糟。并想象一下无法更新它是多么容易。

您的目的是初始化哈希图的匿名实例。警告是您的代码所做的比您预期的要多。

我们正在寻找的是一种初始化匿名哈希图实例的方法。上面我们创建了一个匿名子类的哈希图,然后创建了该匿名类的匿名实例。

因为代码的作用比预期的要多,所以我称其为黑客。

我们真正想要的就是这样:

foo(new HashMap<String, String>({"a", "value-a"}, {"c", "value-c"}));

但是可惜这不是有效的爪哇。没有一种方法可以使用键/值对数组以类型的安全方式进行操作。 Java Simple没有表达能力。

Google Collection的ImmutableMap.of静态方法很接近,但这意味着为各种键/值对创建工厂方法的版本。 (请参阅Finnw的答案。)

因此,请保持简单。使用Bart K的解决方案,除非您的代码对此初始化乱扔垃圾。如果是这样,请使用ImmutableMap。或使用“”样式工厂方法滚动自己的哈希图子类。或在实用程序类中创建这些“”样式工厂方法。这是两个键/值对的一对:

public final MapUtil {
    public static <K,V> Map<K,V> makeMap(K k1, V v1, K k2, V v2) {
        Map<K,V> m = new HashMap<K,V>();
        m.put(k1, v1);
        m.put(k2, v2);
        return m;
    }
}

拥抱冗长,并在您的公司同事戴着与您相同的束缚的知识中慰藉。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top