如何处理 Findbugs “可序列化类中的非瞬态非序列化实例字段”?

2022-08-31 16:14:04

考虑下面的类。如果我对它运行Findbugs,它将在第5行上给我一个错误(“可序列化类中的非暂时性不可序列化实例字段”),但在第7行上不会。

1 public class TestClass implements Serializable {
2
3  private static final long serialVersionUID = 1905162041950251407L;
4
5  private Set<Integer> mySet;      // Findbugs error
6
7  private HashSet<Integer> myOtherSet;
8
9 }

这是正确的,因为java.util.Set从不在其层次结构中实现Serializable,而java.util.HashSet确实如此。但是,最佳做法是针对接口而不是具体实现进行编码。

我怎样才能最好地处理这个问题?

我可以在第3行添加一个@Suppresswarnings(理由=“没有错误”,值=“SE_BAD_FIELD”)。我在实际代码中有很多集合和列表,我担心它会在我的代码中散落太多。

有更好的方法吗?


答案 1

但是,最佳做法是针对接口而不是具体实现进行编码。

我认为不,在这种情况下不是。Findbugs非常正确地告诉您,一旦您在该字段中具有不可序列化的实现,就有可能遇到一个。这是你应该处理的事情。如何,这取决于类的设计。NotSerializableExceptionSet

  • 如果这些集合在类中初始化并且从未从外部设置,那么我认为声明字段的具体类型绝对没有错,因为字段无论如何都是实现细节。请在公共接口中使用接口类型。
  • 如果集合通过公共接口传递到类中,则必须确保它们实际上是 。为此,请创建一个接口并将其用于您的字段。然后,或者:SerializableSerializableSet extends Set, Serializable
    • 在公共接口中使用,并提供实现它的实现类。SerializableSet
    • 检查通过传递给类的集合,如果不是,请将它们复制到某些内容中。instanceof Serializable

答案 2

我知道这是一个已经回答过的老问题,但只是为了让其他人知道,如果你对序列化该特定字段没有兴趣,则可以将该字段设置为瞬态,这将修复您的FindBugs错误。Set<Integer>

public class TestClass implements Serializable {

    private static final long serialVersionUID = 1905162041950251407L;
    private transient Set<Integer> mySet;

}

我更喜欢这种方法,而不是强迫你的API用户投射到你的具体类型,除非它只是内部的,那么Michael Borgwardt的答案更有意义。