Javaアノテーション

Javaの注釈は、コードに関する情報を提供します。Javaの注釈は、それらが注釈付けするコードに直接的な影響を与えません。Javaの注釈チュートリアルでは、次のことについて見ていきます;

  1. 組み込みのJavaの注釈
  2. カスタム注釈の書き方
  3. 注釈の使用方法とReflection APIを使用して注釈を解析する方法。

Javaの注釈

Java 1.5 は注釈を導入し、現在では Hibernate、Jersey、および Spring のような Java EE フレームワークで広く使用されています。Java アノテーションは、プログラム自体に埋め込まれたプログラムに関するメタデータです。これは注釈解析ツールまたはコンパイラによって解析できます。また、注釈の利用可能性をコンパイル時のみまたは実行時まで指定することもできます。Java の注釈が登場する前は、プログラムのメタデータは Java コメントや Javadoc を介して利用可能でしたが、注釈はそれ以上のことができます。注釈のメタデータは実行時にも利用可能であり、注釈解析ツールはそれを使用してプロセスフローを決定することができます。たとえば、Jersey web サービス では、URI パターンに対してメソッドに PATH 注釈を追加し、実行時には、Jersey が与えられた URI パターンに対して呼び出すメソッドを解析します。

Java カスタム注釈

Creating custom annotation is similar to writing an interface, except that the interface keyword is prefixed with _@_ symbol. 我々は注釈でメソッドを宣言することができます。 Javaのカスタム注釈の例を見て、その機能と重要なポイントについて議論します。

package com.journaldev.annotations;

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

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo{
	String author() default "Pankaj";
	String date();
	int revision() default 1;
	String comments();
}

Javaの注釈に関するいくつかの重要なポイントは次のとおりです:

  1. 注釈メソッドにはパラメータを持たせることはできません。
  2. 注釈メソッドの戻り型は、プリミティブ、String、Enums、注釈、またはこれらの配列に制限されています。
  3. Javaの注釈メソッドにはデフォルト値を持たせることができます。
  4. 注釈にはメタ注釈がアタッチされることがあります。メタ注釈は、注釈に関する情報を提供するために使用されます。

Javaのメタ注釈

メタ注釈には5つのタイプがあります:

  1. @Documented – この注釈を使用する要素は、javadocや類似のツールによって文書化されるべきであることを示します。このタイプは、その注釈がクライアントによって注釈の要素の使用に影響を与える型の宣言に注釈を付けるために使用されるべきです。型の宣言がDocumentedで注釈されている場合、その注釈は注釈の要素の公開APIの一部となります。
  2. @Target – アノテーション型が適用可能なプログラム要素の種類を示します。いくつかの可能な値はTYPE、METHOD、CONSTRUCTOR、FIELDなどです。Targetメタアノテーションが存在しない場合、そのアノテーションは任意のプログラム要素に使用できます。
  3. @Inherited – アノテーション型が自動的に継承されることを示します。ユーザーがクラス宣言でアノテーション型をクエリする場合、クラス宣言にこの型のアノテーションがない場合、クラスのスーパークラスが自動的にこの型のアノテーションをクエリされます。このプロセスは、この型のアノテーションが見つかるか、クラス階層の最上位(Object)に到達するまで繰り返されます。
  4. @Retention – アノテーション付きの型がどのくらいの期間保持されるかを示します。これはRetentionPolicy引数を取ります。その可能な値はSOURCE、CLASS、RUNTIMEです。
  5. @Repeatable – アノテーション型が繰り返し可能であることを示します。

Javaの組み込みアノテーション

Javaは、組み込みのアノテーションを5つ提供しています。

  1. @Override – スーパークラスのメソッドをオーバーライドする場合、この注釈を使用してコンパイラにメソッドをオーバーライドしていることを通知します。したがって、スーパークラスのメソッドが削除または変更された場合、コンパイラはエラーメッセージを表示します。なぜ常にメソッドをオーバーライドする際にjava override annotationを使用する必要があるかを学びます。
  2. @Deprecated – メソッドが非推奨であることをコンパイラに知らせたい場合は、この注釈を使用します。Javaでは、javadocで、なぜこのメソッドが非推奨であるか、および使用する代替手段が何かについての情報を提供することを推奨しています。
  3. @SuppressWarnings – これは、特定の警告を無視するようにコンパイラに指示するためだけのものであり、たとえばジェネリックスでローデータ型を使用する場合です。保持ポリシーはSOURCEであり、コンパイラによって破棄されます。
  4. @FunctionalInterface – この注釈は、インターフェースがfunctional interfaceであることを意図していることを示すためにJava 8で導入されました。
  5. @SafeVarargs – 注釈の付いたメソッドやコンストラクタの本体が、その可変引数パラメーターに対して潜在的に安全でない操作を行わないことをプログラマーが主張しています。

Javaのアノテーションの例

上記の例でJavaの組み込みアノテーションの使用と、私たちが作成したカスタムアノテーションの使用を示すJavaの例を見てみましょう。

package com.journaldev.annotations;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class AnnotationExample {

	public static void main(String[] args) {
	}

	@Override
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 1)
	public String toString() {
		return "Overriden toString method";
	}

	@Deprecated
	@MethodInfo(comments = "deprecated method", date = "Nov 17 2012")
	public static void oldMethod() {
		System.out.println("old method, don't use it.");
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 10)
	public static void genericsTest() throws FileNotFoundException {
		List l = new ArrayList();
		l.add("abc");
		oldMethod();
	}

}

I believe above java annotation example is self-explanatory and showing the use of annotations in different cases.

Javaアノテーションの解析

Reflectionを使用してクラスからJavaのアノテーションを解析します。アノテーションの保持ポリシーがRUNTIMEである必要があることに注意してください。そうでないと、その情報は実行時に利用できず、データを取得できません。

package com.journaldev.annotations;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class AnnotationParsing {

	public static void main(String[] args) {
		try {
			for (Method method : AnnotationParsing.class.getClassLoader()
					.loadClass(("com.journaldev.annotations.AnnotationExample")).getMethods()) {
				// メソッドにMethodInfoアノテーションが存在するかどうかを確認します
				if (method.isAnnotationPresent(com.journaldev.annotations.MethodInfo.class)) {
					try {
						// メソッドで利用可能なすべてのアノテーションを反復処理します
						for (Annotation anno : method.getDeclaredAnnotations()) {
							System.out.println("Annotation in Method '" + method + "' : " + anno);
						}
						MethodInfo methodAnno = method.getAnnotation(MethodInfo.class);
						if (methodAnno.revision() == 1) {
							System.out.println("Method with revision no 1 = " + method);
						}

					} catch (Throwable ex) {
						ex.printStackTrace();
					}
				}
			}
		} catch (SecurityException | ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}

上記のプログラムの出力は次のとおりです:

Annotation in Method 'public java.lang.String com.journaldev.annotations.AnnotationExample.toString()' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=1, comments=Main method, date=Nov 17 2012)
Method with revision no 1 = public java.lang.String com.journaldev.annotations.AnnotationExample.toString()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.oldMethod()' : @java.lang.Deprecated()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.oldMethod()' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=1, comments=deprecated method, date=Nov 17 2012)
Method with revision no 1 = public static void com.journaldev.annotations.AnnotationExample.oldMethod()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.genericsTest() throws java.io.FileNotFoundException' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=10, comments=Main method, date=Nov 17 2012)

Reflection APIは非常に強力であり、Java、J2EEフレームワーク(Spring、Hibernate、JUnitなど)で広く使用されています。JavaのリフレクションについてはJavaのリフレクションを確認してください。これでJavaのアノテーションの例チュートリアルは以上です。何か学ぶことができれば幸いです。Javaアノテーションの更新:

  1. Servlet Specs 3.0は、Servletの構成と初期化パラメーターのためのアノテーションの使用を導入しました。詳細は、Java Servletチュートリアルを参照してください。
  2. 私たちはStruts 2でアノテーションを使用してアクションクラスや結果ページを構成することができます。動作する例については、Struts 2 Hello World Annotation Exampleをチェックしてください。

参考: Oracle website

Source:
https://www.digitalocean.com/community/tutorials/java-annotations