これはアノテーションで行うことができます!
エラーを発生させるには、を使用Messagerしてメッセージを送信しますDiagnostic.Kind.ERROR。短い例:
processingEnv.getMessager().printMessage(
    Diagnostic.Kind.ERROR, "Something happened!", element);
これは、これをテストするためだけに書いた非常に単純な注釈です。
この@Marker注釈は、ターゲットがマーカーインターフェイスであることを示しています。
package marker;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Marker {
}
そうでない場合、注釈プロセッサはエラーを引き起こします。
package marker;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedAnnotationTypes("marker.Marker")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public final class MarkerProcessor extends AbstractProcessor {
    private void causeError(String message, Element e) {
        processingEnv.getMessager()
            .printMessage(Diagnostic.Kind.ERROR, message, e);
    }
    private void causeError(
            Element subtype, Element supertype, Element method) {
        String message;
        if (subtype == supertype) {
            message = String.format(
                "@Marker target %s declares a method %s",
                subtype, method);
        } else {
            message = String.format(
                "@Marker target %s has a superinterface " +
                "%s which declares a method %s",
                subtype, supertype, method);
        }
        causeError(message, subtype);
    }
    @Override
    public boolean process(
            Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        Elements elementUtils = processingEnv.getElementUtils();
        boolean processMarker = annotations.contains(
            elementUtils.getTypeElement(Marker.class.getName()));
        if (!processMarker)
            return false;
        for (Element e : roundEnv.getElementsAnnotatedWith(Marker.class)) {
            ElementKind kind = e.getKind();
            if (kind != ElementKind.INTERFACE) {
                causeError(String.format(
                    "target of @Marker %s is not an interface", e), e);
                continue;
            }
            if (kind == ElementKind.ANNOTATION_TYPE) {
                causeError(String.format(
                    "target of @Marker %s is an annotation", e), e);
                continue;
            }
            ensureNoMethodsDeclared(e, e);
        }
        return true;
    }
    private void ensureNoMethodsDeclared(
            Element subtype, Element supertype) {
        TypeElement type = (TypeElement) supertype;
        for (Element member : type.getEnclosedElements()) {
            if (member.getKind() != ElementKind.METHOD)
                continue;
            if (member.getModifiers().contains(Modifier.STATIC))
                continue;
            causeError(subtype, supertype, member);
        }
        Types typeUtils = processingEnv.getTypeUtils();
        for (TypeMirror face : type.getInterfaces()) {
            ensureNoMethodsDeclared(subtype, typeUtils.asElement(face));
        }
    }
}
たとえば、これらは次の正しい使用法です@Marker。
ただし、これらを使用@Markerすると、コンパイラエラーが発生します。
これは、このテーマを始めるのに非常に役立つと思ったブログ投稿です。
小さな注意:以下のコメント投稿者が指摘しているのは、MarkerProcessor参照Marker.classしているため、コンパイル時に依存しているということです。上記の例は、両方のクラスが同じJARファイル(たとえば)に含まれることを前提に作成しましたmarker.jarが、常に可能であるとは限りません。
たとえば、次のクラスを持つアプリケーションJARがあるとします。
com.acme.app.Main
com.acme.app.@Ann
com.acme.app.AnnotatedTypeA (uses @Ann)
com.acme.app.AnnotatedTypeB (uses @Ann)
次に、のプロセッサ@Annは別のJARに存在し、アプリケーションJARのコンパイル中に使用されます。
com.acme.proc.AnnProcessor (processes @Ann)
その場合、循環JAR依存関係が作成されるためAnnProcessor、のタイプを@Ann直接参照することはできません。これは、あくまでも参考にできるようになる@AnnことでString名またはTypeElement/ TypeMirror。