Repeating Annotationをちょっと試してみた

Java8より使用できるようになったAnnotationの重複指定を試してみました。
現時点での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;

「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におきました。