Annotation Element Declarations

Defines an attribute of an annotation.

Syntax

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:
  • public,
  • abstract,
  • and any number of annotations that are applicable to the annotation element

intermixed in any order.

type is one of the following:
  • A primitive type,
  • the type, Class (possibly parameterized),
  • String,
  • any enum type,
  • any other annotation type that does not have an element of this annotation type (directly or indirectly), or
  • an array of any of these types of max dimensionality 1.
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:
  • if the element's type is an annotation type, a use of that annotation type,An example of this is:
    SuppressWarnings elementName() default @SupressWarnings("all");
  • otherwise, a constant expression whose type is the same as the element's declared type.

Syntax Elements

1 A declaration of an annotation element.

Usage

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.

Default Elements

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.

Restrictions

Inheritance

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.

Cyclic Elements

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.

Examples

Cyclic Annotation Reference

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();	}

Default Elements

@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)
}

Value Element

@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") })
}

Notes

  1. An annotation where all elements have a 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")
  2. The Java compiler in Eclipse, version 2022-12 (4.26.0) (Build 20221201-1913), and versions prior, has a bug that disallows the use of the array-dims with the error message:Latest Eclipse version as of writing.
    Extended dimensions are illegal in an annotation attribute declaration

    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.

    Eclipse uses an incremental compiler that introduces runtime errors to the bytecode output, (instead of crashing), if it encounters certain issues with code. The compiler produces a 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()));
    	}
    }