以下のクラスを検討してください。 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(justification = "No bug"、values = "SE_BAD_FIELD")を追加できます。実際のコードには非常に多くのセットとリストがあり、コードが散らかるのが怖いです。
もっと良い方法はありますか?
ただし、具体的な実装ではなく、インターフェイスに対してコーディングすることをお勧めします。
いいえ、この場合はそうではありません。 Findbugsは、そのフィールドに非シリアル化可能なNotSerializableException
実装があるとすぐにSet
にぶつかるリスクがあることを正確に伝えます。これはあなたが対処すべきものです。方法は、クラスの設計に依存します。
Serializable
であることを確認する必要があります。それを行うには、インターフェースSerializableSet extends Set, Serializable
を作成し、それをフィールドに使用します。次に、次のいずれか:SerializableSet
を使用し、それを実装する実装クラスを提供します。instanceof Serializable
を介してクラスに渡されたコレクションを確認し、そうでない場合は、何かにコピーします。これはすでに答えられている古い質問ですが、他の人が知っているように、Set<Integer>
フィールドは、FindBugsエラーを修正する特定のフィールドをシリアル化することに興味がない場合は一時的です。
public class TestClass implements Serializable {
private static final long serialVersionUID = 1905162041950251407L;
private transient Set<Integer> mySet;
}
APIのユーザーに具体的な型へのキャストを強制するのではなく、このメソッドの方が好きです。それが内部的なものである場合を除き、Michael Borgwardtの答えはより意味があります。
これらのCritical
警告メッセージを取り除くには、クラスに次のメソッドを追加します。
private void writeObject(ObjectOutputStream stream)
throws IOException {
stream.defaultWriteObject();
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
}
キャプチャヘルパーを使用して、渡されたSetが2つのインターフェイスをサポートしていることを確認できます。
private static class SerializableTestClass<T extends Set<?> & Serializable> implements Serializable
{
private static final long serialVersionUID = 1L;
private final T serializableSet;
private SerializableTestClass(T serializableSet)
{
this.serializableSet = serializableSet;
}
}
public static class PublicApiTestClass
{
public static <T extends Set<?> & Serializable> Serializable forSerializableSet(T set)
{
return new SerializableTestClass<T>(set);
}
}
このようにして、特定の実装の詳細を確認/要求せずにSerializableを強制するパブリックAPIを使用できます。
コレクションフィールドにfindbugs-excludeフィルターを使用します。
<Match>
<Field type="Java.util.Map" />
<Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
<Field type="Java.util.Set" />
<Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
<Field type="Java.util.List" />
<Bug pattern="SE_BAD_FIELD" />
</Match>
http://findbugs.sourceforge.net/manual/filter.html を参照してください
内部表現には具体的なSerializableセットを使用しますが、パブリックインターフェイスにはSetインターフェイスを使用します。
public class TestClass implements Serializable {
private static final long serialVersionUID = 1905162041950251407L;
private HashSet<Integer> mySet;
public TestClass(Set<Integer> s) {
super();
setMySet(s);
}
public void setMySet(Set<Integer> s) {
mySet = (s == null) ? new HashSet<>() : new HashSet<>(s);
}
}