9

In javax.annotation.processing package there is a interface Processor in which there is a function:

/**
     * Processes a set of annotation types on type elements
     * originating from the prior round and returns whether or not
     * these annotation types are claimed by this processor.  If {@code
     * true} is returned, the annotation types are claimed and subsequent
     * processors will not be asked to process them; if {@code false}
     * is returned, the annotation types are unclaimed and subsequent
     * processors may be asked to process them.  A processor may
     * always return the same boolean value or may vary the result
     * based on chosen criteria.
     *
     * <p>The input set will be empty if the processor supports {@code
     * "*"} and the root elements have no annotations.  A {@code
     * Processor} must gracefully handle an empty set of annotations.
     *
     * @param annotations the annotation types requested to be processed
     * @param roundEnv  environment for information about the current and prior round
     * @return whether or not the set of annotation types are claimed by this processor
     */
    boolean process(Set<? extends TypeElement> annotations,
                    RoundEnvironment roundEnv);

The Java API AbstractProcessor implements above interface. Now I created my own processor class:

public class MyProcessor extends AbstractProcessor {
   ...
   @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

        for (TypeElement annotation: annotations) {
            // How can I get the class of the annotation ?
        }
    }
}

My questions:

  1. The API doc tells me the annotations in the process function are

the the annotation types requested to be processed

Then, why is it with type TypeElement not java.lang.annotation.Annotation ? I get confused by this because I am not sure whether the annotations actually mean the elements that being annotated or the real annotations annotating elements.

  1. Because of my 1st question above, how can I get each annotation's class from the TypeElement?
Leem.fin
  • 40,781
  • 83
  • 202
  • 354

1 Answers1

5

There is a package javax.lang.model which follows a mirror-based design described in Mirrors: Design Principles for Meta-level Facilities of Object-Oriented Programming Languages. It's a greatly designed abstraction used in (but not limited to) the annotation processing framework.

  1. Then, why is it with type TypeElement not java.lang.annotation.Annotation?

    When you design a framework, it's important to keep it open (available for extension). You never know what future versions of the language will bring. You need to stay flexible assuming a new form of metadata may appear.

    I get confused by this because I am not sure whether the annotations actually mean the elements that being annotated or the real annotations annotating elements.

    It's "the real annotations annotating elements" since you are processing annotation types.

    for (TypeElement typeElement : annotations) {
        // it's likely the ElementKind.ANNOTATION_TYPE
        typeElement.getKind();
    
        // elements annotated with the annotation
        environment.getElementsAnnotatedWith(typeElement);
    }
    
  2. Because of my 1st question above, how can I get each annotation's class from the TypeElement?

    The TypeElement represents your annotation class.

To read:

  1. https://bracha.org/mirrors.pdf (it will take a lot of time to process)

  2. https://www.baeldung.com/java-annotation-processing-builder (it's a simple annotation processor)

  3. https://github.com/rzwitserloot/lombok/blob/master/src/core/lombok/core/AnnotationProcessor.java (it's a good practical example)

  4. The Javadoc of the package and the core classes such as Processor, AnnotatedConstruct, Element, TypeElement, TypeMirror.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • Thanks for the answer. I think you misunderstand my 2nd question. I know `TypeElement` represents annotation class but it is not annotation class. I mean how can I get the `Class` instance of my annotation. For example if I have a custom annotation `@MyAnnotation`, I want to get `MyAnnotation.class` from the `TypeElement`, is it possible? – Leem.fin Sep 27 '19 at 07:36
  • About your answer to my 1st question. I also know the open-close principle, but `Annotation` is a interface, it is not a concrete implementation of anything. I still look for a convincing reason why `Set extends TypeElement> annotations` is not a `Set extends Annotation>` type in its design & variable name is saing `annotations`. Besides, you missed my question that I wonder whether that set is representing all my custom annotations or all elements annotated by my annotations. – Leem.fin Sep 27 '19 at 07:43
  • @Leem.fin `java.lang.Annotation` isn't a part of the `javax.lang.model` abstraction (that's why it's `Set extends TypeElement>`) and I guess `annotations` is used in [a broader sense](https://en.wikipedia.org/wiki/Metadata) (it doesn't necessarily refer to the `Annotation` interface we know). Note that the Javadoc can be changed easily not effecting source code. – Andrew Tobilko Sep 27 '19 at 08:24
  • @Leem.fin I included it ("the real annotations annotating elements"): it's your annotations. To get elements annotated with your annotations you need an environment and you do `environment.getElementsAnnotatedWith` (see the snippet above) – Andrew Tobilko Sep 27 '19 at 08:27
  • *"representing all my custom annotations"* is a bit inaccurate. *"representing all the annotations I support (or my annotation processor supports)"* is more precise (see [`@SupportedAnnotationTypes`](https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/SupportedAnnotationTypes.html)) – Andrew Tobilko Sep 27 '19 at 08:34
  • Thanks for the clarification and the links in your answer, it is more clear to me now :) . – Leem.fin Sep 27 '19 at 09:57
  • @Leem.fin you're welcome. I will add an example of a custom processor a bit later today – Andrew Tobilko Sep 27 '19 at 09:58