Repeating Annotationをちょっと試してみた
Java8より使用できるようになったAnnotationの重複指定を試してみました。
現時点でのJavaのVersionはこれです。
- Java version
- 1. Annotationの対象クラス
ここでReview Annotationを「methodA」に対して2つ指定
package com.my.test; import java.util.List; @Review(ReviewerName = "Mr. D", ReviewDate = "2013/04/15") public class Sample { @NonNull String str; @NonNull List<String> list; // List<@NonNull String> list2; 注釈型はこの種類の宣言に使用できません public static void main(String... args) { Sample sample = new Sample(); sample.methodA(); sample.methodB(); } @Review(ReviewerName = "Mr.A", ReviewDate = "2013/04/01") @Review(ReviewerName = "Mr.C", ReviewDate = "2013/04/14") //★Java8以前ではエラーになっていた void methodA() { System.out.println("method A"); } @Review(ReviewerName = "Mr.B", ReviewDate = "2013/04/01") void methodB() { System.out.println("method B"); } }
- 2. Review Annotation
@Repeatableの引数では次の3のコンテナクラスを指定
package com.my.test; import java.lang.annotation.*; @Repeatable(ReviewContainer.class) public @interface Review { String ReviewerName(); String ReviewDate(); }
- 3. ReviewContainer
上記2のReviewを指定(この場合、どっちを先にcompileするのでしょうか?)
package com.my.test; public @interface ReviewContainer { Review[] value(); }
- 4. InfoProcessor
使用しているAnnotation、Annotationを指定している要素、Annotationのキーと値を表示
package com.my.test; import java.lang.annotation.IncompleteAnnotationException; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Messager; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("*") public class InfoProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { System.out.println(String.format("Annotation:%s" , annotation.toString())); Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation); for (Element ele : elements) { System.out.println(String.format(" Element:%s", ele)); List<? extends AnnotationMirror> annotationMirrors = ele.getAnnotationMirrors(); for (AnnotationMirror mirror : annotationMirrors) { Map<? extends ExecutableElement, ? extends AnnotationValue> values = mirror.getElementValues(); for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : values.entrySet()) { System.out.println(String.format(" key=%s, value=%s", entry.getKey(), entry.getValue())); } } } } return true; } }
- 5. NonNull
package com.my.test; public @interface NonNull{ }
試しにこのAnnotationを1.Sampleの中で以下のように記述したのですが、エラー発生したのでコメントアウト
List<@NonNull String> list2;
- 6. 上記4のInfoProcessorを指定してコンパイル
- 7. コンパイル時に以下の内容が表示
「methodA」に対して「Review」Annotationを2つ指定していたのですが、ここでは「ReviewContainer」が適用されていてその値に「Review」Annotationが配列で表示
- ファイルの構成
この画面は以前にJavaFXで作成しました2013-03-23 - tomoTakaの日記
今更ですが、今回初めてAnnotationを処理するコードを書いてみました、、、
Annotationの詳細は、id:skrbさんのこの記事Java技術最前線 - 「Java SE 6完全攻略」第94回 アノテーションを処理する その1:ITproを参考にさせていただきました。とっても勉強になります!
全コードはここtomoTaka01/RepeatingAnnotationSample · GitHubにおきました。