18

我有一个问题,因为我有点困惑(或者我可能没有注意到一些明显的事情)。假设我有一些源代码,其中包含很多类,其中包含大量像这样定义的静态字段:

public final class ConverterTYPE  {
    private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>() {
        {
            put("A", new Byte((byte)12));
            put("B", new Byte((byte)13));
        }
    };

}

众所周知,静态字段不会被序列化。

但是,Java(和 Eclipse)抱怨“可序列化的类没有声明 long 类型的静态最终 serialVersionUID 字段”。为什么他们没有注意到 static 不会被序列化?

@SuppressWarnings("serial")下一个问题:用它来消除所有此类警告是否是解决此问题的正确方法?

编辑:

我的类都没有实现 Serializable 接口(或者它们的超类都没有)。并且 Eclipse 正HashMap<String, Byte>用它的警告指出。为什么它没有检测到它是静态场?

4

2 回答 2

25

仅仅因为该字段可能没有被序列化并不意味着它引用的东西本身永远不会被序列化!其他人/事物可以获得对该映射的引用并尝试直接对其进行序列化,或者将其用作可序列化类中的实例成员等。我看到它是私有的,但要确保它永远不会在当前类之外被访问或设置为实例成员超出了编译器的范围(无论如何反射都是不可能的)。

一种可能的解决方案是简单地避免使用带有初始化程序样式的匿名子类并执行以下操作:

private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>();

static {  
  STRING_MAP.put("A", new Byte((byte)12));
  STRING_MAP.put("B", new Byte((byte)13));
}

在大多数情况下,结果几乎相同,并且您的代码中没有充斥着匿名类。

于 2011-01-20T16:02:27.737 回答
21

但是,Java(和 Eclipse)抱怨“可序列化的类没有声明 long 类型的静态最终 serialVersionUID 字段”。为什么他们没有注意到 static 不会被序列化?

错误消息和您的类中有一个最终静态成员变量的事实(至少,我是这样解释您的描述)彼此没有任何关系。

您的类实现了 interface Serializable,或者您的类的超类之一实现了这一点。所以编译器注意到你的类是可序列化的。可序列化的类应该有一个名为的静态最终字段serialVersionUID,用于在序列化类的实例时进行版本控制。

使用注解@SuppressWarnings("serial")会使编译器对丢失的serialVersionUID. 所以是的,您可以使用它来消除警告消息,但更好的解决方案是让您的类不实现Serializable(直接或间接),如果它不打算被序列化。

于 2011-01-20T15:49:51.710 回答