Defines an attribute of an annotation.
An annotation element declaration consists of:
1 | modifier-list type name
( ) array-dims
default default-value ; |
where...
modifier-list | is a possibly empty set of keywords and annotations that can
contain:
intermixed in any order. |
type | is one of the following:
|
name | is an identifier denoting the name of the element. |
array-dims | is the [ token followed by the ] token,
used together to indicate that the element's type is an array. The
brackets can instead be included in the type,
but are allowed here for consistency with older versions of Java.
|
default-value | is:
|
1 A declaration of an annotation element.
Annotation element declarations are used exclusively in the body of annotation declarations. They're used to define attributes that must/may be specified when the declared annotation is used. The annotation element declarations in the following example are highlighted turquoise, and the annotation uses are higlighted yellow.
@interface SomeAnnotation {
int size(); // Required annotation element
String website() default "javaref.net"; // Optional annotation element
}
@SomeAnnotation(size = 4) class AnnotationTest { // size is required, so it must be specified
@SomeAnnotation(size = 12, website = "javaref.net/annotations/declarations")
int x = 14; // Specify size explicitly
@SomeAnnotation(website = "example.com", size = 10)
void someMethod() { }
}
The type of value that may be provided for an element when using an
annotation is the type specified in
the element declaration. Annotation elements may optionally have both
or either of the keywords public
and abstract
,
but neither one has any effect, since annotation element declarations
are already deemed public
and abstract
.
Annotation elements whose declarations contain a default
clause with a default-value do not
need to be specified when the annotation is utilized. The annotation
can be used as if the element was not declared in the annotation's
declaration, and the annotation use will have the default-value for that element.
Annotation element declarations formally declare abstract
methods in the annotation type they are contained in. No annotation
element is allowed to override a public
or protected
method from either java.lang.Object
or java.lang.annotation.Annotation
.
This is the case despite the method declared by an element declaration
being abstract
.
An annotation element's type may be another annotation. That contained annotation may in turn have one or more elements whose types are also annotations.
An annotation element's type may not be or contain the annotation that the element is declared in; an element's type may not cause a cycle.
value()
Element
If an annotation has an element named exactly value
and
all other elements, if any, have default values, the annotation can
optionally be used and given a value without explicitly specifying an
element name. The provided value is implicitly assigned to the value
attribute of the annotation.
This is an example of a set of annotations whose elements create a cycle. Cyclic annotations will not compile.
@interface First { Second value(); }
@interface Second { Third value(); }
@interface Third { First value(); }
@interface MadeBy {
int age() default 10;
double height() default 6.3;
String name() default "John";
}
class Test {
private @MadeBy int x; // x is annotated with @MadeBy(name = "John", age = 10, height = 6.3)
private @MadeBy("Christine") int y; // y is annotated with @MadeBy(name = "Christine", age = 10, height = 6.3)
private @MadeBy(age = 97) int z; // z is annotated with @MadeBy(name = "John", age = 97, height = 6.3)
}
@interface First { String value() default "Bird"; }
@interface Second { int value() default 10; }
@interface Third { First[] value() default { @First("Dog"), @First("Cat"), @First("Cow") }; }
class X {
@First("Cow") int a; // a is annotated with @First(value = "Cow")
@Second(14) int b; // b is annotated with @Second(value = 14)
@Second(value = 13) int c; // c is annotated with @Second(value = 13)
@Second int d; // d is annotated with @Second(value = 10)
@Third(@First) int e; // e is annotated with @Third(value = { @First(value = "Bird") })
}
default
value
may still be used and given a value without explicitly naming the
attribute the value applies to, so long as the annotation has a value
attribute: @interface Test {
int something() default 10;
int somethingElse() default 20;
String value() default "ABC";
}
@Test("DEF") class X { } // X is annotated with @Test(something = 10, somethingElse = 20, value = "DEF")
Due to Eclipse's compilation process, an annotation element
declaration containing the array-dims
part can still be compiled by Eclipse's compiler, though the compiler
will introduce an unchecked exception to the compiled bytecode. Executing the compiled code results in a java.lang.Error
with the above message.
java.lang.Error
with the above error message as its message
, which is
raised in code attempting to access the annotation such as in the
example below.
An example to reproduce the issue is as follows:
public class AnnotationBug {
@Retention(RetentionPolicy.RUNTIME)
@interface Test {
String value()[] default {}; // Offending line
}
static @Test int x = 10;
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
System.out.println(Arrays.toString(AnnotationBug.class.getDeclaredField("x").getAnnotations()));
}
}