2011-10-25 81 views
4

我想知道为什么当我使用一个匿名实例和一个实例初始化块时,我得到一个“可序列化的类没有声明long类型的静态最终serialVersionUID字段”编译时警告。匿名初始化 - 奇怪的序列化警告

这是我的意思。比方说,我想实例化一个ArrayList和同时添加的东西给它,像这样:

ArrayList<Object> arrayList = new ArrayList<Object>(){{add(new Object());}}; 

如果我编译这一切都是确定,但我得到的serialVersionUID领域缺少警告。现在ArrayList已经实现了可序列化,并且有一个private static final long serialVersionUID那么为什么当我像这样使用它时,它看起来该字段“消失”了,并且我得到了一个没有声明的警告?

+1

这只是愚蠢的。很少有人今天使用Java序列化,这种通用警告是没有根据的。而且我永远无法将引用IDE的Eclipse用户视为**非限定编译器。 – irreputable

+0

相关:[显式serialVersionUID认为有害?](http://stackoverflow.com/questions/419796/explicit-serialversionuid-considered-harmful) –

+0

@irreputable是否有一些注释来压制这一点?我的意思是,如果他们可以为未经检查的演职人员做到这一点,那么您肯定会期望像UID这样的东西可以被忽略。 –

回答

7

当您创建匿名类时,实际上是扩展了ArrayList,因此继承了Serializable接口。

全部Serializable类应该有一个serialVersionUID,以便您可以区分不同的序列化版本的类。由于匿名类型是一个新类,给它一个ID是一个好主意,所以你可以区分它的不同版本。

+3

明白了,所以这就像扩展ArrayList类,然后THAT扩展类有调用“add”的初始化块,但它是一个不同的类,它需要它自己的serialVersionUID(因为它从ArrayList继承Serializable)。由于我创建了一个匿名类,这对我来说并不明显。 –

+1

@AndreiBodnarescu准确无误。匿名类只是用于创建从另一个类扩展的新类的语法糖(在你的情况下,'ArrayList')。 –

+2

@AndreiBodnarescu准确。说了这么多,使用这种双括号语法来收集启动是不鼓励的,因为现在你并没有真正拥有一个ArrayList,而是一些模糊的子类,这可能会在稍后导致一些模糊的问题。你遇到这些问题的可能性不大,但是当你这样做时,它会成为一个头疼的人。它可能是冗长的,但最好只写所有的'add()'语句或初始化一个数组,然后使用它创建列表。 –

2

因为你创建的是本质上是一个子类。这样的子类需要自己的串行版本UID。当你像JPanel一样子类化时,也会发生同样的事情。如果你不需要(de)序列化,这不是一个可怕的问题。

0
new ArrayList<Object>() { 

    { 
     add(new Object()); 
    } 

}; 

你不只是实例,但首先定义的ArrayList一个子类(匿名),然后实例化的子类。

即使有在ArrayList一个private static final long serialVersionUID,因为它是静态,它不是由您的匿名子类继承。所以它缺少这个领域。