理解此警告:可序列化的类不声明静态最终serialVersionUID [英] Understanding this warning: The serializable class does not declare a static final serialVersionUID

查看:122
本文介绍了理解此警告:可序列化的类不声明静态最终serialVersionUID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

由于某些原因,我收到Eclipse的警告:
可序列化的类不声明一个静态的最终serialVersionUID。



这是抱怨匿名类吗?我该怎么做,或者我应该压制它。

解决方案

您使用的语法称为双括号初始化 - 这实际上是一个实例初始化块,它是匿名内部类(当然不是黑客)。所以,当使用这个符号时,你实际上是在定义一个新的类(!)。

您的情况中的问题是 HashMap 实现 Serializable 。该接口没有任何方法,仅用于识别可序列化的语义。换句话说,它是一个标记接口,具体而言,您不必执行任何操作。 ,在反序列化过程中,Java使用称为 serialVersionUID 的版本号来验证序列化版本是否与目标兼容。如果你不提供这个 serialVersionUID ,它将被计算。而且,正如 <$ c $ javadoc中记录的那样c> Serializable ,所计算的值非常敏感,因此建议显式声明它以避免任何反序列化问题。这就是Eclipse抱怨的一点(注意这只是一个警告)。

因此,为避免此警告,您可以添加 serialVersionUID 到您的匿名内部类:

  someMethodThatTakesAHashMap(new HashMap< String,String>( ){
private static final serialVersionUID = -1113582265865921787L;

{
put(a,value-a);
put(c ,value-c);
}
});

但是你忽略了语法的简洁性(你可能甚至不需要它)。 >

因此,另一个选项是通过向您所在的方法添加 @SuppressWarnings(serial)>来忽略警告调用 someMethodThatTakesAHashMap(Map)。这似乎更适合你的情况。



尽管这句话很简洁,但它有一些缺点。首先,如果您在使用双括号初始化初始化的对象上持有引用,则隐式地持有对不符合垃圾回收条件的外部对象的引用。所以要小心。其次(这听起来像是微型优化),双括号初始化有一个非常小的开销。第三,这种技术实际上使用了匿名的内部类,因此我们看到了这些内部类,因此会吃掉一些permgen空间(但是我怀疑这实际上是一个问题,除非您真的滥用它们)。最后 - 这可能是最重要的一点 - 我不确定它是否使代码更具可读性(它不是一个众所周知的语法)。

所以,虽然我喜欢在测试中使用它(为了简洁),我倾向于避免在常规代码中使用它。


I have some static initializer code:

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

For some reason I am receiving a warning from Eclipse: The serializable class does not declare a static final serialVersionUID.

Is this complaining about the anonymous class? What can I do about that, or should I just suppress it.

解决方案

The syntax you're using is called double-brace initialization - which is actually an "instance initialization block that is part of an anonymous inner class" (certainly not a hack). So, when using this notation, you are actually defining a new class(!).

The "problem" in your case is that HashMap implements Serializable. This interface doesn't have any methods and serves only to identify the semantics of being serializable. In other words, it's a marker interface and you concretely don't have to implement anything. But, during deserialization, Java uses a version number called a serialVersionUID to verify that the serialized version is compatible with the target. If you don't provide this serialVersionUID, it will be calculated. And, as documented in the javadoc of Serializable, the calculated value is extremely sensitive and it is thus recommended be explicitly declare it to avoid any deserialization problems. And this is what Eclipse is "complaining" about (note that this is just a warning).

So, to avoid this warning, you could add a serialVersionUID to your annonymous inner class:

someMethodThatTakesAHashMap(new HashMap<String, String>() {
    private static final long serialVersionUID = -1113582265865921787L;

    {
        put("a", "value-a");
        put("c", "value-c");
    }
});

But you loose the conciseness of the syntax (and you may not even need it).

Another option would thus be to ignore the warning by adding a @SuppressWarnings("serial") to the method where you are calling someMethodThatTakesAHashMap(Map). This seems more appropriate in your case.

That all being said, while this syntax is concise, it has some drawbacks. First, if you hold a reference on the object initialized using a double-brace initialization, you implicitly hold a reference to the outer object which won't be eligible for garbage collection. So be careful. Second (this sounds like micro optimization though), double-brace initialization has a very a little bit of overhead. Third, this technique actually uses anonymous inner classes as we saw and thus eats a bit of permgen space (but I doubt that this is really a problem unless you really abuse them). Finally - and this is maybe the most important point - I am not sure it makes the code more readable (it's not a well known syntax).

So, while I like to use it in tests (for the conciseness), I tend to avoid using it in "regular" code.

这篇关于理解此警告:可序列化的类不声明静态最终serialVersionUID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆