Search code examples
javaannotations

Java Annotation @Target(ElementType.TYPE_USE) - Also covers declaration contexts?


This compiles perfectly even though the following annotation is not supposed to be used as a declaration annotation.

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


// Foo annotation
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@interface Foo {}

@Foo
class Person {}


@Foo
interface Emittable() {}

In the above example, the Foo annotation type is used in the declaration contexts of Person and Emittable types, even though it is targeted only for type contexts, and the funny thing is that the code compiles just fine and runs perfectly Does it mean that ElementType.TYPE_USE also covers the declaration contexts? According to the Java 14 Language Specification, ElementType.TYPE_USE does not cover any declaration contexts. What am I missing?


Solution

  • The currently-accepted answer is incorrect.

    The relevant documentation is at https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html and says

    The constant TYPE_USE corresponds to the 15 type contexts in JLS 4.11, as well as to two declaration contexts: type declarations (including annotation type declarations) and type parameter declarations.

    In other words, TYPE_USE is a special case. The rationale for is that when defining a type qualifier, programmers may often want to write it on declarations as well as uses. This is laid out in https://docs.oracle.com/javase/specs/jls/se14/html/jls-9.html#jls-9.7.4 which says:

    two of the nine clauses - for class, interface, enum, and annotation type declarations, and for type parameter declarations - mention "... or type contexts" because it may be convenient to apply an annotation whose type is meta-annotated with @Target(ElementType.TYPE_USE) (thus, applicable in type contexts) to a type declaration.

    The currently-accepted answer quotes text that is about a different matter: how to interpret the annotations in

    class C {
      @MyDeclAnno @MyTypeAnno Object myField;
    }
    

    where MyDeclAnno is a declaration annotation and MyTypeAnno is a type annotation. The JLS grammar parses both annotations on the declaration. However, the text quoted in the currently-accepted answer notes that @MyTypeAnno as is actually applied to the type Object whereas @MyDeclAnno is actually applied to the declaration of the field myField.