Java

【リフレクションとアノテーション】プログラムにメタ情報を付加する

アノテーションとは?

アノテーションとはクラスやインタフェース、メソッドやフィールド、パッケージなどに対してメタデータとして付加情報を記入する機能のことだよ

アノテーションの分類

・マーカーアノテーション

名前だけでデータのないアノテーション(@Overrride, @Deprecated)

・単一アノテーション

データを一つ持つアノテーション(@SupperessWarning)

・フルアノテーション

複数のデータを持つアノテーション

・メタアノテーション

定義しているアノテーションにのみつけられるアノテーション(@Target, @Retention)

付加情報の付け方

コメントを使う場合
/*
Created: Jan 1 2018
Created By: Tomo
Last Modified: Jan 1 2020
Last Modified By: Tomo
Revision: 3
*/

public class Foo{
/*Fooクラスの内容*/
}
アノテーション使う場合
@interface ClassInfo { 
  String created();
  String createdBy();
  String lastModified();
  String lastModifiedBy();
  int revision();
}

@ClassInfo(
 created = “Jan 31 2005”,
 createdBy = “James Gosling”,
 lastModified =“Feb 9 2005”,
 lastModifiedBy =“Ken Arnold”,
 revision =3
)public class Foo{
/*Fooクラスの内容*/
}

アノテーションの定義方法・使い方

//Foo.java
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.MRTHOD)
@interface BugsFixed {String[] value(); }

public class Foo {
  @Test public static void m1() { } //”Testアノテーションに追加”
  public static void m2() { }
  @Test public static void m3() {throw new RuntimeException("Boom");}
  public static void m4() { } 
  @Test public static void m5() { } 
  public static void m6() { } 
  @Test public static void m7() {throw new RuntimeException("Crash");}
  public static void m8() { } 
}

//RunTests.java
import java.lang.reflect.*;
public class RunTests {
  public static void main(String[] args) throws Exception {
      int passed = 0, failed = 0;
      for (Method m : Class.forName(args[0]).getMethods()) {
          if (m.isAnnotationPresent(Test.class)) { 
            try {
              m.invoke(null);
              passed++;
            } catch (Throwable ex) {
              System.out.printf("Test %s failed: %s %n", m, ex.getCause());
              failed++; }
              } 
         }
    System.out.printf("Passed: %d, Failed %d%n", passed, failed);
  }
}
アノテーションの定義方法

・ “@Retantionアノテーション名”で有効範囲を設定する
→”@Retention(RetentionPolicy.RUNTIME)“のように設定する

RetentionPolicy名 説明
RetentionPolicy.CLASS アノテーション情報はコンパイル時に保存されるが実行時にはVMによって保持されない。
RetentionPolicy.RUNTIME アノテーション情報はコンパイル時に保存され、実行時にもVMによって保持される。
RetentionPolicy.SOURCE アノテーション情報はコンパイル時に破棄される。ソースコード内のみで有効。

・ “@Targetアノテーション名”でメソッド・フィールドを限定する
→”@Target (ElementType.TYPE)“のように設定する

ElementType名 説明
ElementType.ANNOTATION_TYPE アノテーション型に指定できることを示す。
ElementType.CONSTRUCTOR コンストラクタに指定できることを示す。
ElementType.LOCAL_VARIABLE ローカル変数に指定できることを示す。
ElementType.FIELD フィールドに指定できることを示す。
ElementType.METHOD メソッドに指定できることを示す。
ElementType.PACKAGE パッケージに指定できることを示す。
ElementType.PARAMETER メソッド引数に指定できることを示す。
ElementType.TYPE クラス、またはインタフェース(アノテーション型を含む)、列挙型に指定できることを示す

・ “@interfaceアノテーション名”でアノテーションを定義する
→各キーには、”default”キーワードでデフォルト値を設定する
値の指定は、”@アノテーション名(キー名=値)”という形で行う
デフォルト値が指定されている場合、値の指定は省略できる
単一アノテーションで値のキー名が”value”の場合のみ、キー名を省略できる

 

アノテーションの種類

・@Override
記述するメソッドが親クラスのメソッドをオーバーライドしていることを明示する

・@Deprecated
記述するメソッドの仕様が非推奨であることを明示する

@Deprecated class DeprecatedClass {
    @Override public boolean equals(Object obj) {
        return this == obj;
    }
}

・@SuppressWarning
引数にメッセージを指定することで、記述するメソッドによる警告を非表示にすることができます。

@SuppressWarnings(value = {"serial"})

 

・@Target
独自に定義したアノテーションが何を対象としているか宣言するために使われます。

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
public @interface NewAnnotation {
}

 

・@Retention
コンパイル時やプログラム実行時にアノテーションの情報を保持するかどうか決めるために使われる

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
public @interface NewAnnotation {
}

 

・@Test
そのメソッドがテストメソッドであることを示す。このメソッドにテストを記述する。従来のJUnitでメソッド名がtestで始まるメソッドと同じ。

・@Before
このアノテーションが付加されたメソッドは、@Testアノテーションが付いたメソッドを実行するたびに事前に実行されることを意味する。JUnit4以前のsetup()メソッドと同じ。

・@After
このアノテーションが付加されたメソッドは、@Testアノテーションが付いたメソッドを実行するたびに、必ず後から実行されることを意味する。JUnit4以前のtearDown()メソッドと同じ。

・@BeforeClass
このアノテーションが付加されたメソッドは、そのテストクラスを呼び出す前に実行される。

・@AfterClass
このアノテーションが付加されたメソッドは、そのテストクラスを呼び出した後に実行される。

・@author
作成者の名前を記述

・@param
引数と引数の説明を記述

・@return
戻り値の説明を記述

・@version
クラスやメソッドなどのバージョンを記述

・@see
他の関連するクラスやメソッドなどの参照先を記述

1 2