アノテーションのインスタンスを取得する

このエントリはJava Advent Calendar 2012の第19日目のエントリです。
昨日は @yoshioterada さんの「Concurrency Update (jsr166e)のご紹介」でした。
明日は @kis さんの「Javaでのパターンマッチを考える」です。

お二人に挟まれて、私は自分の少し恥ずかしい話をします。今日のテーマはアノテーションのインスタンスについてです。

事の起こり

私はある日、こういうメソッドに出くわしました。

select(Annotation...)

なるほどAnnotationクラスを引数として渡すのね、と初めは軽く考えてしまったのですが、実際にこのメソッドを呼ぼうとしたとき困りました。

最初に書いたコードはこうです。(笑

select(@Customized);

コンパイルエラーになりました。というかEclipseなので赤線が出ました。ここでアレっ?と思ったわけです。そこでコードを次のように直してみました。

select(Customized.class);

それでもやっぱり赤線が出ます。おや? メソッドが呼べない! もう大混乱です。

Annotationクラスって何でしょう

メソッドの定義がおかしいのでしょうか。いやいや、呼べないようなメソッドが定義されているはずはないので(なにしろJavaEEのAPIです)、私のコードが間違っている可能性の方が極めて高いです。頭を冷やしてよく考えてみましょう。

アノテーションでよく使うのはこういうコードですよね。

@Override
public String toString() {
     // ...
}

この@Overrideはアノテーションによる注釈付けをするときの書き方なわけです。

ではCustomized.classは・・・? 変数に代入してみるとよくわかります。

Class<Customized> type = Customized.class;

なるほど、Customized.classはCustomizedクラスを表すクラスインスタンスです。

とするとAnnotationクラスはどういった場面で登場するのでしょうか。こういうときは初心に帰って、Java docを開いてみます。java.lang.annotation.Annotationインターフェースの「使用」を見てみると、Class#getAnnotations()というメソッドの戻り値がAnnotation[]になっています。リフレクションですね。

@Customized
public class ObtainAnnotation {
     public static void main(String[] args) {
          Annotation[] annotations
               = ObtainAnnotation.class.getAnnotations();

          for (Annotation a : annotations) {
               System.out.println(a);
          }
     }
}
@Customized()

ようやく分かってきました。アノテーションによって注釈付けされた要素に付いている、実際のアノテーションを表すのがAnnotationクラスのインスタンスです。 続きを読む アノテーションのインスタンスを取得する