The target values of the ElementType constants from 1 to 10 in Table 25.2 indicate declaration contexts—that is, a context where a program element is declared. Annotations with these target values are called declaration annotations. For example, an annotation type declaration with the target value ElementType.CONSTRUCTOR is only applicable to a constructor declaration.
@Target(ElementType.CONSTRUCTOR)
@interface Tag {}
———————————————————————————————
class Item {
@Tag public Item() {} // Declaration context. Annotates constructor Item.
}
However, an annotation type declaration with the target value ElementType.PARAMETER is applicable to a parameter declaration in contexts where such parameter declarations are permitted. Note that several target values can be specified in the @Target meta-annotation.
@Target({ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@interface Tag {}
———————————————————————————————-
double circleArea(@Tag double r) { // Declaration context. Annotates parameter r.
return 5.0;
}
Note also that the context of the target value ElementType.ANNOTATION_TYPE and the context of the target value ElementType.TYPE are overlapping, as the latter not only includes annotation type declarations, but also other reference type declarations (class, interface, and enum).
The target value ElementType.TYPE_USE indicates type contexts—that is, where a type is used in a declaration or an expression. Annotations with this target value are called type annotations.
@Target(ElementType.TYPE_USE)
@interface Tag {}
———————————————————————————————-
java.lang. @Tag Integer iRef1 = 100; // (1) Type context. Annotates Integer.
@Tag Integer iRef2 = 100; // (2) Type context. Annotates Integer.
@Tag java.lang.Integer iRef3 = 100; // (3) Declaration context.
Compile-time error!
@Tag int compute() { return (@Tag int) 3.14; }// (4) Type context is int type.
@Tag void compute(int i) {} // (5) No return type specified.
// Compile-time error!
In both (1) and (2) above, @Tag is a type annotation on the type Integer, as this type is used in the declaration of the variables. The code at (3) does not compile, as the type annotation @Tag is used in a declaration context. Note how the position of the annotation changes the context of the annotation at (1) and (3). At (4), the type annotation @Tag is on the return type int of the non-void method. As the method at (4) is a void method, there is no return type that is applicable for the type annotation @Tag, so the compiler flags an error.
Consider the following annotation type with the target value ElementType.FIELD:
@Target(ElementType.FIELD)
@interface Tag {}
——————————————————————————————————
java.lang. @Tag Integer iRef1 = 100; // (1a) Type context. Compile-time error!
@Tag Integer iRef2 = 100; // (2a) Declaration context. Annotates iRef2.
@Tag java.lang.Integer iRef3 = 100; // (3a) Declaration context. Annotates iRef3.
At both (2a) and (3a), the annotation @Tag is a declaration annotation on the field, as these are field declarations. The code at (1a) does not compile, as the declaration annotation @Tag is used in a type context.
An annotation can be both a declaration and a type annotation, as illustrated by the code below.
@Target({ElementType.TYPE_USE, ElementType.FIELD})
@interface Tag {}
——————————————————————————————————
java.lang. @Tag Integer iRef1 = 100; // (1b) Type context. Annotates Integer.
@Tag Integer iRef2 = 100; // (2b) Declaration and type context.
@Tag java.lang.Integer iRef3 = 100; // (3b) Declaration context. Annotates iRef3.
An ElementType value can only occur once in the value() element of the meta-annotation @Target. The following specification of the value() element of the meta-annotation @Target will not compile.
@Target(value = {ElementType.METHOD, ElementType.FIELD,
ElementType.METHOD}) // Compile-time error!
@interface Tag {}
By default (when the @Target meta-annotation is not present on the annotation type declaration), the annotation can be applied in any declaration context except type parameter declarations. In addition, the annotation is not permitted in any type contexts.
@interface Tag {} // No target specified.
——————————————————————————————————————————————————————————————————————————
@Tag class Box<@Tag E> { // Class declaration: OK.
// Type parameter: Compile-time error!
<@Tag T> void doIt(T t) {} // Type parameter: Compile-time error!
void doTask() throws @Tag Exception {} // Type context: Compile-time error!
int iTod(double d) { return (@Tag int) d; }// Type context: Compile-time error!
@Tag boolean flag; // Field declaration. OK.
}
An empty @Target(value = {}) annotation is allowed, shown at (1) below, but it does not allow the annotation to be directly applied to any program element, as shown at (3) below. However, this annotation can still be used as the type of an element in other annotation type declarations, as shown at (2), which can be applied normally, as shown at (4).
@Target({}) // (1) Empty target.
@interface Exclusive {}
@interface ExtraExclusive {
Exclusive value() default @Exclusive; // (2) Annotation as element type.
}
—————————————————————————————————————————————————————————————————————————————-
@Exclusive class Titanium {} // (3) Compile-time error!
@ExtraExclusive class Krypton {} // (4) OK.
The annotation type declaration below shows that the MusicMeta type annotation is applicable to any type (class, interface, and enum), method, or field.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface MusicMeta {}
The @MusicMeta annotation is applied below on a class at (1), on a field at (2), and on a method at (3), as permitted by the annotation type declaration shown above. Not surprisingly, applying it on a local variable at (4) results in a compile-time error.
@MusicMeta public class Composition { // (1) On class
@MusicMeta private String description; // (2) On field
@MusicMeta public void play() { // (3) On method
// @MusicMeta int volume; // (4) Compile-time error!
}
}