Annotations

Annotations are used to mark program elements, possibly with extra information. Annotations are designed so that markers can be read and used by annotation processors at various points along the lifecycle of program development.

Annotations provide a means of adding structured information to program elements that can be processed easily.

Syntax

1 @ name ( )
2 @ name ( element-value )
3 @ name ( element-value-list )

where...

name is a qualified or simple name that refers to the annotation.
element-value is a constant expression or another (nested) annotation that matches the type of the annotation's value element.
element-value-list is a map of annotation elements to constant expressions or other annotations. The map is specified as a comma-separated list of key-value pairs of the form:
element-name = value
where element-name specifies which element the value is assigned to and value specifies the value to assign.

Syntax Elements

1 An annotation without attributes provided (a marker annotation).

2 An annotation that specifies a single attribute, value, of its annotation type.

3 A normal annotation, with attributes explicitly named.

Usage

Annotations associate supplementary information with a Java element in a program. They can apply to:

The location in source code that an annotation may be present at to apply to a certain element is dictated by the syntax for that element. For example, see Method Declarations. Semantic rules invovling the annotation's declared targets define whether annotations deemed to apply to certain elements are illegal and will raise compiler errors.

Annotations that apply to declarations are almost always specified in the declaration's modifier list, intermixed with keyword modifiers, such as public, protected, static, final, etc. Annotations that apply to type uses may appear in these same locations (subject to some constraints) or may appear more closely to the type. For details, see below.

Targets

Although not required, an annotation declaration can restrict (or expand) its use to certain program elements using the @java.lang.annotation.Target meta-annotation. The @Target annotation has a non-default java.lang.annotation.ElementType[] member, which specifies the types of program elements that the annotation may be applied to. The ElementType array may not contain duplicates when used as an argument to the @Target annotation.

There are 10 possible targets that an annotation declaration may specify in a @Target meta-annotation:

Enum Constant Target Description Index
TYPE Type any class, enum, and interface declarations (including any @interface annotation declarations). 1
ANNOTATION_TYPE Annotation Type any @interface annotation declarations. 2
METHOD Method any method declaration, including abstract declarations and annotation element declarations. 3
CONSTRUCTOR Constructor any constructor declaration. 4
FIELD Field any field declaration, including constants declared in @interfaces and enum constants. (Note that annotations targeting fields can be used on their own member constants.) 5
PARAMETER Parameter any method parameter (not including receiver parameters). 6
LOCAL_VARIABLE Local Variable any local variable declaration, including those in the header of a for loop or try-with-resources statement. 7
PACKAGE Package implementation-chosen package declarations. 8
TYPE_PARAMETER Type Parameter any type parameter declaration. 9
TYPE_USE Type Use the use of a type. 10

How Targets Work

Annotations whose declarations do not specify a target can be applied to:

That is, they can be applied to all annotatble program elements except Type Parameters and Type Uses.

Otherwise, if @Target is applied to an annotation's declaration, that annotation may be applied to the union of the types permitted by each ElementType specified in the @Target annotation. For example, if @Target({ TYPE, FIELD }) is applied to a declaration, the annotation may be applied to both type declarations (e.g. classes, interfaces, etc.) and fields.

TYPE Target

The TYPE target allows an annotation to be applied to any type declaration.

ANNOTATION_TYPE Target

The ANNOTATION_TYPE target is a subset of the TYPE target. The ANNOTATION_TYPE allows an annotation to apply to annotation declarations.

An annotation that targets both TYPE and ANNOTATION_TYPE can be applied to the same set of program elements as an annotation that targets only TYPE.

METHOD Target

Allows an annotation to apply to methods. Such annotations may be put within the modifier-list of a method declaration.

Annotation declarations with this target can apply to annotation elements, including their own annotation elements.

CONSTRUCTOR Target

Allows an annotation to target any constructor declaration. The annotation is put in the modifier-list of the declaration.

FIELD Target

Allows an annotation to target any field declaration. Such annotations can only be placed in the modifier-list of a field declaration. Reflectively, the annotation can be accessed from any java.lang.reflection.Field that is a part of the annotated declaration, though the annotation cannot be applied to only some fields in a multi-field declaration.

PARAMETER Target

Allows an annotation to target any parameter in a:

The annotation is put in the modifier-list of the parameter.

Note that this target does not allow an annotation to be applied to receiever parameters, as annotations that are a part of a receiver parameter may only be applied to the type use within the receiver parameter declaration.

LOCAL_VARIABLE Target

Allows an annotation to target any local variable declaration, including those inside the headers of for loops and try statements. The annotation is put in the modifier-list, just like the keyword final if it is present.

PACKAGE Target

Allows an annotation to target package declarations. In any given package, only one such package declaration is allowed to be annotated. The annotation is put in front of the declaration, in the declaration's "modifier list." As of Java 8, there are no modifiers applicable to a package declaration other than annotations.

Implementation-Specific Canonical Package Declaration

Implementations typically choose to specify a canonical package declaration, and require that this be the only package declaration that be annotated. Many implementations follow suggestions made by the specification that this canonical declaration be in a file called package-info.java which is situated directly in the package.

This means that, in some implementations of the Java compiler, an annotated package declaration must go in a specific file, rather than go in any file subject to the constraint that there is only one such annotated declaration per package.

TYPE_PARAMETER Target

Annotations with this target can be applied to type parameters in a declaration of a generic:

The type parameters declared in the type-parameter-list of these program elements can each be annotated with annotations targetnig TYPE_PARAMETERS. Such annotations are located textually immediately in front of the name of the type variable in the declaration.

TYPE_USE Target

The TYPE_USE target allows an annotation to be applied to types in type contexts. Type contexts are contexts where a type is used to denote the literal type of a value, object, or other thing. For example, the type in a simple variable declaration is used to denote the type of value the variable can store, and the type in an extends clause is used to denote what the type is being extended. In some cases, types can be used as other objects, such as a simple container for a nested class; the TYPE_USE target does not permit an annotation to be applied in these other cases.

The TYPE_USE target permits an annotation to be located as follows:

TYPE_USE does not permit an annotation to be used on:

despite each of these being uses of types.

Multi-applicability

An annotation that targets TYPE_USE while also targeting any of the following declarations:

may apply to both the declaration and its type if used within the declaration's modifier list. This may happen even if the declaration declares type parameters (in the case of constructor and method declarations, considering a constructor's type to be the type of object it constructs).

Retention

Meta Annotations

element-value and element-value-list

Uses

Show and explain uses for annotations.

Examples

Self-Application of Annotations

Annotation Applied to Own Members

TYPE_USE Examples

Notes

  1. A bug in some versions of the Eclipse IDE compiler allows an annotation to be applied to a generic method's return type twice if the annotation targets TYPE_USE. This can be done if the method declares any type parameters and the annotation is placed within the method's modifier-list as well as immediately before the method's return type, so long as the return type is not void.

    Attempting to access the annotation on the return type, via reflection, raises a java.lang.annotation.AnnotationFormatError, reflecting the invalid application of the annotation in bytecode.

    Code to reproduce the error is as follows:

    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface A {	}
    @A <T> @A int test() {// Problematic line
    	return 0;
    }
    • This compilation issue occurs even if the aforementioned annotation is @Repeatable, resulting in a java.lang.annotation.AnnotationFormatError when the annotation is accessed, as from the following code:
      @Target(ElementType.TYPE_USE)
      @Retention(RetentionPolicy.RUNTIME)
      @interface As {
      	A[] value();
      }
      @Target(ElementType.TYPE_USE)
      @Retention(RetentionPolicy.RUNTIME)
      @Repeatable(As.class)
      @interface A {	}
      @A <T> @A int test() {// Problematic line
      	return 0;
      }

      Such results in an error because of the way annotations are compiled.

  2. A bug in some versions of the Eclipse IDE compiler allows an annotation targeting TYPE_USE to be applied to void in a method declaration if the declaration declares a type parameter list. Code containing such an annotation successfully compiles by the IDE's compiler, and the annotation is not available during runtime, even if its retention is RUNTIME. Code to reproduce the behavior is as follows:
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface A {	}
    <T> @A void test() {	}

    The correct behavior is for a compilation error to be raised.

  3. A bug in some versions of the Eclipse IDE compiler prevents an annotation targeting TYPE_USE from being applied to a constructor declaring type-parameters if located after that constructor's type-parameter-list:
    @Target(TYPE_USE)
    @interface A {	}
    class Ex {
    	<T> @A Ex() {	} // Compiler complains that "@" symbol is not allowed here
    }

    Curiously, duplicating the annotation by placing it in the modifier list of the constructor, before the type-parameter-list, raises an additional error that @A is duplicated:

    @Target(TYPE_USE)
    @interface A {	}
    class Ex {
    	@A <T> @A Ex() {	} // Compiler complains that "@" symbol is not allowed here
    }
  4. In many declarations, annotations targeting TYPE_USE can be construed as being either:
    • immediately before the simple name of the declaration's type (see above),
    • or in the modifier list of the declaration (see above).

    A simple example is in the method declaration:

    @A int one() {	return 1;	}

    In these cases, the annotation still applies to the declaration's type, (and is considered to apply only once). It is possible for an annotation to be unambiguously placed into either of these two parts of a declaration in any declaration that permits type parameters. For example, if the method declaration above declared a type parameter list:

    @A <T> int one() {	return 1;	}

    the annotation @A then unambiguously falls within the method declaration's modifier-list. This phenomenon is possible for method declarations and constructor declarations, alike. This phenomenon gives rise to the two aforementioned distinct rules listed above that say where TYPE_USE annotations are permitted, but do not have any effect on how the annotation applies, as annotations at the end of the modifier-list of a declaration that target TYPE_USE will still apply to the declaration's type.

  5. Types that are not:

    • primitive,
    • top-level types stored within the default package,
    • or used to name a constructor,

    can be fully qualified by a package name when used as a declaration's type, deterring the ability of an annotation in the declaration's modifier-list from applying to both the declaration and the declaration's type. Such annotations targeting any of the five potentially ambiguous declarations as well as TYPE_USE can be made to only apply to the declaration, since the simple name closest to the declaration's modifier list will be a package name, not a type name:

    @Target({ TYPE_USE, FIELD })
    @interface A {}
    
    class Test {
    	@A Object someField; // @A applies to Object and the whole declaration
    	@A java.lang.Object someOtherField; // @A applies only to the whole declaration
    }

    In the code example, since @A targets both field declarations and type use, it applies to someField's declaration and its type: Object, since Object is a simple name. In the declaration of someOtherField, @A can only apply to the declaration, since the the simple name closest to @A is java which names a package.

    This is also possible to use for statically nested types, even in the default package.