チェッカーフレームワーク(org.jetbrains:annotation)の使い方メモ
IntelliJ IDEAとかAndroid Studioを使っている人は、メソッドの横の方に@が書かれているのを見たことがあるかと思います。

(Android Studioで実際に表示されるのかは知らないけど、ツイッターで観測している限りアンドロイダーの人で「この@Contractって何」ってツイートしている人がいたのでおそらく表示されている)
ここにカーソルを合わせると、メソッドの性質について情報が表示されます。
例1:次のようなメソッドの場合には@Contract("null -> fail; !null -> !null")と表示されます。
nullを引数に渡すと例外が発生するnullでない引数を渡すとnullでない値が返される
例2:つぎのメソッドの場合には@NotNullと表示されます。
- どのような引数を渡しても必ず
nullでない値が返される
この情報が表示されることで、あるクラスのあるメソッドの引数にnullを渡すと例外が発生するとか、List<UserInformation>を返すメソッドなんだけどnullを返してくることがあるっぽいといった性質がわかるので、事前にそれらの対策を織り込んだコードを書くことができると思います。
チェッカーフレームワーク
IntelliJ IDEAで表示されているのはJetBrains製のチェッカーフレームワークのorg.jetbrains:annotationsに基いたメソッドの静的な性質についての情報です。
チェッカーフレームワークはJSR308で提案されたもので、コンパイル時にnull安全性や副作用の有無などを検査するフレームワークです。
詳しくはこのあたりのサイトを読むといいと思います。
ワシントン大学のチェッカーフレームワークのサイト
で、そのレポジトリー
というか、日本語でかなり詳しく書かれた記事
ちなみにチェッカーフレームワーク自体はJava SE8で導入されているものです。
JetBrainsのチェッカーフレームワーク
で、JetBrainsのチェッカーフレームワークに戻ると、このアノテーションセットはmavenセントラルに登録されているので、取ってくることができます。
<dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations</artifactId> <version>13.0</version> </dependency>
dependencies {
compile 'org.jetbrains:annotations:13.0'
}
そして、@で表示されているのと同じ内容のアノテーションを記述すると、横にある@が消えます。

実はこんな偉そうなことを書いている割には、全部のアノテーションを使ったことがあるわけではなく、@Contractと@NotNullくらいしかわかってないので、僕が知っている限りの書き方をメモしておきます。
@NotNull
- メソッドに付与された場合は、そのメソッドは
nullを返さないことが保証されることを意味するnullを返すようなコードを書いていると、コードハイライトされる
- メソッドのパラメーターに付与された場合は、引数に
nullを渡すことはできない - フィールドの付与した場合は、フィールドに
null値を設定することは許されない
@Contract
メソッドの性質に関する契約を記述するアノテーションで、boolean型の値pureとString型の値valueを設定する
pureは副作用に関する契約を記述するvalueはメソッドの性質について記述する- メソッドの性質は
引数部 -> 作用 ; 引数部 -> 作用 ; ...のような形で引数部 -> 作用を;で区切った形で記述する - 引数部は
引数 , 引数 , ...のように引数をカンマで区切った形で記述する - 引数には渡される可能性のある値を記述する。なお、引数には次の文字列が使用できる
_: 任意の引数null:null値!null:nullでない値true:booleanのtruefalse:booleanのfalse
- 作用には返される値を記述する。なお、作用には次の文字列が使用できる
null:null値が返される!null:nullでない値が返されるtrue:booleanのtrueが返されるfalse:booleanのfalseが返されるfail: 例外が返されることを意味するany: 任意の値 : 使うこともできるがあまり意味がない
- メソッドの性質は
例1. 二つの引数をとって、どちらともnullでない場合にはnullでない値が返され、いずれか一方がnullだった場合には例外が発生する、副作用のないメソッドについては次のように記述する。
@Contract(value = "null, _ -> fail; _, null -> fail; !null, !null -> !null", pure = true)
例2. 一つの引数をとるが、どのような値が渡されても絶対にnullが返されないメソッドの場合は次のように記述する。
@Contract("_ -> !null")
実はこれで良かったりもする。
@NotNull
例3. 引数なしのメソッドで、絶対にnullが返されないメソッド
@Contract("-> !null")
例4. 二つの引数を取り、最初の引数がnullの場合にはnullが返されるメソッド
@Contract("null, _ -> null")
javadocを読んでいるとその他のアノテーションにこのようなものがあります。
@Nls: 文字列がローカライズされる必要がある@NonNls: 文字列がローカライズされる必要はない@Nullable: 引数やフィールドにnullを渡しても大丈夫@PropertyKey: リソースにあるプロパティキーに必ず含まれている文字列@TestOnly: テストコードにのみ使用することが許されるメソッドやコンストラクター/プロダクションコードでは使用してはいけない
使い方
ドキュメントとして使うのも、まあ、悪くはないんだけど、せっかくコードハイライトしてくれる(eclipseとnetbeansのことは忘れている)のだから、コードを書く前にそのメソッドに求める性質を記述してから書くというのが妥当な使い方だと思います。
まず、メソッドに求める性質を記述します。

そして、性質を満たすようにコードを書きます。

すると、あら不思議!nullとか例外レベルのコード品質が保証されたコードが出来上がります(「品質」という言葉をここで使うのは、かなりためらっている)。
これで、nullとか例外に関するテストコードを書く手間が少し省けますね(あるに越したことはない)。
さあ、あなたもチェッカーフレームワークでADD(Annotation Driven Development)な生活を!