Annotations (Java 5) attach information to declarations and, since Java 8, to uses of types. They do not change what the code does by themselves; the compiler, annotation processors, tools and frameworks read them, at compile time or through reflection at run time (JLS 9.6 and 9.7).
Declaring an annotation interface
AnnotationInterfaceDeclaration:
{InterfaceModifier} @ interface TypeIdentifier AnnotationInterfaceBody
AnnotationInterfaceElementDeclaration:
{AnnotationInterfaceElementModifier} UnannType Identifier ( ) [Dims] [default ElementValue] ;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Review {
String reviewer(); // required element
int priority() default 3; // optional, with a default
String[] tags() default {};
Status status() default Status.OPEN;
enum Status { OPEN, DONE } // nested types are allowed
}
- An annotation interface is an interface declared with
@interface. Its superinterface is alwaysjava.lang.annotation.Annotation; it cannot have anextendsclause or type parameters. - Each method declares an element. Elements have no parameters, no type
parameters and no
throwsclause. - An element’s type must be a primitive type,
String,Classor a parameterisation of it such asClass<? extends Number>, an enum type, another annotation type, or a one-dimensional array of one of these. An annotation interface may not contain an element of its own type, directly or indirectly. - Defaults and values must be constant expressions, class literals, enum constants,
annotations or array initialisers of these.
nullis never allowed. - The body may also declare constants and nested types.
Writing annotations
| Form | Example | Use |
|---|---|---|
| Normal | @Review(reviewer = "Ada", priority = 1) | Any annotation; elements by name, in any order |
| Marker | @Override | No elements given: all have defaults, or there are none |
| Single-element | @SuppressWarnings("unchecked") | The only element given is named value, so the name is left out |
For an array element, a single value may be written without braces:
@SuppressWarnings("unchecked") means
@SuppressWarnings({"unchecked"}). Annotations are modifiers, so they may
be mixed with other modifiers in any order, though by convention they come first.
Predefined annotations
The JLS gives these annotations of java.lang and
java.lang.annotation a meaning to the compiler (JLS 9.6.4):
| Annotation | Effect | Since |
|---|---|---|
@Override | Error unless the method overrides or implements a supertype’s method (from Java 6 also an interface’s) | 5 |
@Deprecated | Warns when the element is used. Elements since and forRemoval (Java 9); forRemoval = true gives a stronger warning | 5 |
@SuppressWarnings | Turns off the named warnings, such as "unchecked", "deprecation", "removal" and "preview", inside the element | 5 |
@SafeVarargs | Promises a generic varargs method does nothing unsafe with its array, silencing heap pollution warnings. Allowed on static, final and (since Java 9) private methods, and on constructors | 7 |
@FunctionalInterface | Error unless the interface is a functional interface | 8 |
@Retention | How long the annotation is kept (below) | 5 |
@Target | Where the annotation may be written (below) | 5 |
@Inherited | A class annotation is inherited by subclasses, for reflection | 5 |
@Repeatable | The annotation may be written more than once on the same element | 8 |
@Documented (Java 5) asks javadoc to show the annotation in
the documentation. @Native (Java 8) marks a constant field that native
code refers to.
Retention
RetentionPolicy | Kept in |
|---|---|
SOURCE | The source only; discarded by the compiler (@Override, @SuppressWarnings) |
CLASS | The class file, but not loaded at run time. The default when @Retention is absent |
RUNTIME | The class file, and readable by reflection (@Deprecated, @FunctionalInterface) |
Targets
ElementType | Applies to | Since |
|---|---|---|
TYPE | Class, interface, enum, record and annotation declarations | 5 |
FIELD | Fields and enum constants | 5 |
METHOD | Methods, and annotation elements | 5 |
PARAMETER | Parameters of methods, constructors, lambdas and catch clauses | 5 |
CONSTRUCTOR | Constructors | 5 |
LOCAL_VARIABLE | Local variables, including resources and pattern variables | 5 |
ANNOTATION_TYPE | Annotation interface declarations (meta-annotations) | 5 |
PACKAGE | Package declarations | 5 |
TYPE_PARAMETER | Type parameter declarations | 8 |
TYPE_USE | Any use of a type | 8 |
MODULE | Module declarations | 9 |
RECORD_COMPONENT | Record components | 16 |
Without @Target, an annotation may be used on any declaration, but
not in type contexts.
Repeatable annotations
An annotation can be written several times on one element if it is marked
@Repeatable with a containing annotation interface, whose
value element is an array of it. The compiler wraps the repeats in the
container:
@Repeatable(Schedules.class)
@interface Schedule { String day(); }
@interface Schedules { Schedule[] value(); }
@Schedule(day = "Mon")
@Schedule(day = "Thu") // stored as @Schedules({@Schedule(day = "Mon"), @Schedule(day = "Thu")})
void backup() {}
The container must have retention at least as long and targets no wider than the repeatable annotation.
Type annotations
Since Java 8 (JSR 308) an annotation whose target includes TYPE_USE can
be written on any use of a type, so that checkers can track properties such as
nullness:
@NonNull String name;
List<@NonNull String> names;
String @NonNull [] array; // the array is non-null
@NonNull String [] elements; // the elements are non-null
Map.@NonNull Entry<K, V> entry; // on a nested type: after the dot
new @Interned String("x");
Object o = (@NonNull Object) value;
void read() throws @Critical IOException;
class Box<@Immutable T> extends @Readonly Base implements @Remote Service {}
void m(@ReadOnly Box<T> this) {} // a receiver parameter
An annotation in front of a declaration is a declaration annotation, a type
annotation or both, depending on its targets. For array types, the annotation applies
to the type it immediately precedes: before the element type for the elements, before
a [] for that level of array. A type annotation cannot be written on a
whole qualified name before the simple name: @NonNull java.lang.String is
an error, while java.lang.@NonNull String is right.