Tbpgr Blog

Ruby プログラマ tbpgr(てぃーびー) のブログ

書籍 パーフェクトJava | アノテーション

概要

Javaアノテーションについて。
アノテーションはプログラムの構成要素に付与するメタ情報。
アノテーションを修飾子として適用することを「アノテーションの適用」と呼ぶ。

アノテーションの記述

public等、他の修飾子と同じ業に書くことができるが
独立した行に書くのが慣例

記述例

  @SuppressWarnings("unused")
  public static void main(String[] args) {
    String hoge;
  }

標準のアノテーション

アノテーション 内容
Overriede オーバーライドを明示
Deprecated 非推奨を明示
SuppressWarnings 警告抑制

アノテーション記述ルール

以下の構文でアノテーションを宣言する

[アクセス制御修飾子] @interface アノテーション名 {
  アノテーション要素
}

この際、引数の指定・throwsの付与・ジェネリックメソッドは禁止です。

アノテーション要素のないアノテーションはマーカーアノテーションと呼ぶ。
アノテーションの要素は処理のないメソッド定義と同じです。

コード例

package perfect.annotation;

public @interface HogeAnnotation {
  String hoge();
  String hige() default "hige";
  int value();
}

アノテーションの適用

アノテーションの適用時には以下の記述ルールがあります。
要素名=値を指定
要素名がvalueの場合は要素名を省略可能

@HogeAnnotation(hoge = "hoge")
public static void maine() {
  :
}

メタアノテーション

アノテーションに適用するアノテーション
標準メタアノテーションは以下。

アノテーション 内容
Documented アノテーションJavaDocの文書化対象とすることの指示
Inherited アノテーションが自動的に継承されることの指示
Retention アノテーションの存在期間を指示
Target アノテーションの対象要素を指示
Retention

3種類のEnum(RetentionPolicy)を持つ
SOURCE:アノテーションをソースファイルのみに残す
CLASS:アノテーションをソースファイルとクラスファイルにのみに残す
RUNTIME:アノテーションをソースファイルのみに残し、実行時も利用可能にする

・デフォルトはCLASS
・SOURCEはコンパイル時のみ利用するようなケース
・RUNTIMEは実行時にリフレクションで読み取る場合などに使用

Target

対象を指定する。対象はElementTypeのEnumで指定。

以下、ElementTypeのソースから抜粋

    public static final ElementType TYPE;
    public static final ElementType FIELD;
    public static final ElementType METHOD;
    public static final ElementType PARAMETER;
    public static final ElementType CONSTRUCTOR;
    public static final ElementType LOCAL_VARIABLE;
    public static final ElementType ANNOTATION_TYPE;
    public static final ElementType PACKAGE;

サンプルコード

アノテーション本体1

package perfect.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HogeAnnotation {
  String hoge();
  // デフォルトを設定可能
  String hige() default "hige";
}

アノテーション本体2

package perfect.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseValue {
  String value();
}

アノテーション宣言コード

package perfect.annotation;

public class SampleAnnotation {
  @HogeAnnotation(hoge = "hoge")
  public String hello() {
    String message = "hello";
    return message;
  }

  // 要素名がvalueの場合は名称を省略可能
  @UseValue("value")
  public String doValue() {
    String message = "doValue";
    return message;
  }

  @SuppressWarnings("unused")
  public static void main(String[] args) {
    String hoge;
  }
}

アノテーション利用側

package perfect.annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SampleAnnotationClient {
  public String useAnnotation() throws SecurityException, NoSuchMethodException, InstantiationException,
      IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class<SampleAnnotation> clazz = SampleAnnotation.class;
    SampleAnnotation sample = clazz.newInstance();
    Method hoge = clazz.getMethod("hello");
    HogeAnnotation hogeAnnotation = hoge.getAnnotation(HogeAnnotation.class);

    StringBuilder sb = new StringBuilder();
    sb.append(hogeAnnotation.hoge());
    sb.append(",");
    sb.append(hogeAnnotation.hige());
    sb.append(":");
    sb.append(hoge.invoke(sample));
    return sb.toString();
  }

  public String useValueAnnotation() throws SecurityException, NoSuchMethodException, InstantiationException,
      IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class<SampleAnnotation> clazz = SampleAnnotation.class;
    SampleAnnotation sample = clazz.newInstance();
    Method doValue = clazz.getMethod("doValue");
    UseValue useValue = doValue.getAnnotation(UseValue.class);

    StringBuilder sb = new StringBuilder();
    sb.append(useValue.value());
    sb.append(":");
    sb.append(doValue.invoke(sample));
    return sb.toString();
  }

  public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchMethodException,
      InstantiationException, IllegalAccessException, InvocationTargetException {
    SampleAnnotationClient sampleAnnotationClient1 = new SampleAnnotationClient();
    System.out.println(sampleAnnotationClient1.useAnnotation());

    SampleAnnotationClient sampleAnnotationClient2 = new SampleAnnotationClient();
    System.out.println(sampleAnnotationClient2.useValueAnnotation());
  }

}

出力例

hoge,hige:hello
value:doValue