SpotBugs(FindBugs)のWarningに対処する
SpotBugsについての投稿は/tag/SpotBugsにあるので参照されたい
SpotBugs(FindBugs)の警告への対処だが、四種類ある。これについて説明する。
サンプルの警告
こんなコードを書いてみる。
public class Sample {
int a;
public Sample(int a) {
this.a = a;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Sample)) return false;
return ((Sample)o).a == a;
}
}
別に問題は無いと思うのだが、SpotBugsは不平を言ってくるのだ。
foobar.Sample defines equals and uses Object.hashCode() [Troubling(14), High confidence]
何が気に入らないのかというと、equalsを定義しているのに、hashCodeを定義していないという。
こちらとしては必要無いのだが、FindBugsの方としては「必須」と決めつけているらしい。
SpotBugsのパースペクティブを見てみると、以下のような表示だ。説明と対処法が表示されている。
※ここでは英語で表示されているが、これはEclipseを完全に英語モードにしたがためである。Eclipse:完全に英語モードにする方法を参照のこと。
FindBugsおすすめの方法で対処する
先の説明には「必要無いならこれを入れろ」とある。その通りに、以下のようなコードを挿入する。
public int hashCode() {
assert false : "hashCode not designed";
return 42; // any arbitrary constant will do
}
あまり気分の良いものではない。
素直に修正する
ごく普通に対処する。この方法が最も一般的だろう。後からSampleをMapやSetに入れることに決定しても問題無い。
public int hashCode() {
return a;
}
そもそも警告を出さないようにする
EclipseでSpotBugs(FindBugs)を使ってみる、その1で説明するように、検出するバグの種類を設定できるため、このバグの検出を排除してしまうことにする。
まず、このバグのタイプを確認する。
タイプが「HE」であることがわかる。パターンは「HE_EQUALS_USE_HASHCODE」というものだ。
次にEclipseもしくはプロジェクトについてのSpotBugsの設定を表示させ、このバグを検出させないようにする。
- 左側のJavaの下にあるSpotBugsをクリック
- Detector configurationタブを選択
- Pattern(s)をクリックしてABC順に並べる
- しかし、ここがわかりにくいのだが、Co|Eq|HEというパターン名なのでCのところにある。
- FindHEmismatchのチェックをはずす
下の方は、このディテクタの検出するバグの説明である。hashCode()およびequals()がらみの問題を検出するとある。
そして、まさに今回の問題「HE_EQUALS_USE_HASHCODE」が含まれていることがわかる。
この状態で再度SpotBugsを走らせると、見事にバグ検出がなくなる。
その場所だけ警告を出さないようにする
以上述べた対処方法としては、「素直にhashCode()を定義する」「そもそもこの問題を検出させないようにする」だったのだが、この「一箇所だけ検出させない」ようにすることもできる。
通常のJavaのSuppressWarningsアノテーションと同様にSuppressFBWarningsアノテーションを使えば良いのだ(FBになっているのはFindBugs時代の名残と思われる)。
では、「何らかのライブラリを入れねばならないのか?」と言われるとさにあらず、自分で作ってしまってよい。SpotBugsはSuppressFBWarningsがどのパッケージであろうが気にしない。
適当なところに以下のクラスを作成する。
package mypackage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.CLASS)
public @interface SuppressFBWarnings {
String[] value() default {};
String justification() default "";
}
そして、Sampleを以下に変更する。
@SuppressFBWarnings(value={"HE_EQUALS_USE_HASHCODE"}, justification="必要無いので")
public class Sample {
int a;
public Sample(int a) {
this.a = a;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Sample)) return false;
return ((Sample)o).a == a;
}
}
justificationは設定しなくてもよい。ここにはコメントを書くようだが、この内容がいつ使われるのかは不明。
参考
以下を参考にした。
ディスカッション
コメント一覧
まだ、コメントがありません