What are annotations? From Java 5 onwards there is a new reference data type added in the Java language, which allows us to annotate any programming element. Annotations are used like modifiers, which are created by the developer. We can create annotations which can be used with any kind of target type (programming element) within the Java source file. These are kinds of additional modifiers which a developer creates, normally to be used by some other kinds of processing tools (known as Annotation Processing Tools). javadoc
is an example of a similar tool. It works on the Java source file. It processes the source file and generates the documentation. While processing the Java source file the javadoc
utility uses the documentation comments found before any of the elements of the source code, which are normally the class or interface definition, the constructor, the methods, the instance and the class variables, and the member classes and interfaces. Only thing here is that in case of javadoc
the documentation comments, which will be processed by the utility, are the ones which appear just before the modifiers for the element for which the documentation comment is defined, whereas in case of annotation processing tools, the annotated elements within the source file will be used by them. Annotations are equivalent to the modifiers and can be mixed with modifiers. Conventionally, annotations are normally used before all other modifiers, and the rest of the modifiers start from a new line. Another important difference is that the annotations can have attributes for which values can be specified at the time of usage. Some of these attributes can have default values. Let us look at how to define annotations and then how we use them to annotate various programming elements in a Java source file.
An annotation is defined by using the keyword interface
prefixed with @
character as shown below:
1 public @interface NewAnnotation { // this defines an annotation called NewAnnotation 2 3 }
An annotation can have attributes. When we define an annotation, we need to declare what attributes are permissible for the annotation. These lists of attributes for the annotation are defined using the elements of the annotation. The elements of an annotation are of a type and have a name. These elements of an annotation type are declared similar to the methods in an interface. These annotation types are not interfaces, they only use the syntax like an interface. The elements of an annotation can be of the following types only:
primitive types
String
enum
Another annotation
Class
array of any of the preceding types
The element is declared using the abstract method declaration as is done in an interface. So if we want to have an element called attrib1
of type String in the annotation NewAnnotation
, it would be defined as follows:
1 public @interface NewAnnotation { // this defines an annotation called NewAnnotation 2 String attrib1(); // declare an element name attrib1 of type String 3 }
The elements of any annotation can have a default value, which can be specified in the declaration by using the keyword default
, as shown in the following listing:
1 public @interface NewAnnotation { // this defines an annotation called NewAnnotation 2 String attrib1() default "value1"; // default for the attribute attrib1 will be value1 3 }
The methods used for declaring the elements of an annotation type cannot have any parameters nor can they have any kind of throws clause. These cannot be of generic type, i.e. they cannot use the generic type variable. Also while defining an annotation, the annotation type cannot declare any extends clause to extend from any interface; they implicitly extend from the annotation interface from the java.lang.annotation
package.
Any of the programming elements where a modifier is allowed can be annotated. The following are the valid programming elements which may be annotated:
To annotate any element, we use any of the annotation types which have been defined using @interface
along with the modifiers and specify the values for all its elements. Elements which do not have default values have to be compulsorily specified and initialized. While annotating an element the annotation name is preceded by the @
character and the attribute values are specified in parentheses as shown below:
1 @NewAnnotation(attrib1="some value") // annotating the TestAnnotation class 2 public class TestAnnotation { 3 // some valid code 4 }
When annotating any programming element (using an annotation), if the name of the element of the annotation being used is value
, then it is not compulsory to use the element name along with the value of the element. We can simply use the value without using the name, e.g. if the element name of the element in the NewAnnotation
, was value instead of the attrib1, as is currently then, while annotating any element with NewAnnotation
, we need not explicitly specify the element name, as shown in the following listing:
1 @NewAnnotation("some value") // annotating the TestAnnotation class 2 public class TestAnnotation { 3 // some valid code 4 }
When the element type is an array, then it should be initialized using the array initializer, and in case the array has a single element then the braces around the array initializer may be discarded, e.g. if we have an element called updatedBy
of type String[]
, to specify the developers who update the specified element, in our annotation NewAnnotation
, then, it could be used as follows:
1 @NewAnnotation("some value", updatedBy="author1") 2 public class TestAnnotation { 3 // some valid code 4 }
for single value in updatedBy
array, and
1 @NewAnnotation("some value", updatedBy={"author1", "author2", "author3"}) 2 public class TestAnnotation { 3 // some valid code 4 }
for multiple elements of the updatedBy
element.
There are annotations which can be used to annotate an annotation. These can be applied to an annotation to restrict the target (where a particular annotation can be applied), or whether the annotation needs to be retained beyond the Java source code. The annotations which can be applied on an annotation are known as meta-annotations. There are two meta-annotations which are commonly known and used.
The meta-annotation Target
(defined in the java.lang.annotation) is used to restrict the application of the annotation to certain types of programming elements only. The Target
meta-annotation has only one element which is an array of enum type java.lang.annotation.ElementType. The enum values for the ElementType
are as follows:
ANNOTATION_TYPE |
Annotation type declaration |
CONSTRUCTOR |
Constructor declaration |
FIELD |
Field declaration (includes enum constants) |
LOCAL_VARIABLE |
Local variable declaration |
METHOD |
Method declaration |
PACKAGE |
Package declaration |
PARAMETER |
Parameter declaration |
TYPE |
Class, interface (including annotation type), or enum declaration |
So, if we want to restrict the usage of annotation NewAnnotation
to only methods and constructors, then the NewAnnotation
may be annotated using the meta-annotation Target
as shown in the listing below:
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) // restricting
the target elements
public @interface NewAnnotation { // this defines an annotation called
NewAnnotation
String attrib1() default "value1"; // default for the attribute
attrib1 will be value1
}
The annotations which are used in the specific source code are by default retained in the class files, whenever these are compiled. We can control the retention of a specific annotation usage by using the meta-annotation called @Retention
. There are three enum values of the enum type RetentionPolicy
, which can be used as the values of the Retention
meta-annotation. The values are SOURCE
, CLASS
and RUNTIME
. The annotations which have been annotated with a retention value of SOURCE
are not retained beyond the source code, whereas the annotations which have been annotated with a retention value of CLASS
are retained in the class files. These annotations are only recorded in the class files, but may not be available at runtime, where the class is loaded by the VM. The annotations which are annotated with the meta-annotation Retention
with a value of RUNTIME
are retained in the class files and are available at runtime. These annotations can be accessed reflectively by a Java application.
interface
is preceded by the @
symbol.String
. These attributes are defined by using method declarations with no parameters, method name being the attribute name desired, and the method return type is the type of the attribute. The type for an attribute can be any primitive type, String
, enum
type, another annotation, Class
or array of any of these.value
. While annotating a programming element, a value is specified for each attribute, except in cases where the attribute may have a default value declared.Target
could be used to specify the target element types which can be annotated with the annotation being defined. The meta-annotation Retention
can be used to specify the retention policy for the annotation being defined. Depending on where the tool will operate, if the tool operates on the source file, the retention policy can be specified for annotation to be retained only in the source code and not available in the class file.StrinbBuffer
.@Target
annotation having value ANNOTATION_TYPE
is a meta-annotation.1 @interface MyAnnotation{ 2 3 }
Then let’s say in an application we obtain the Class
instance for this annotation by using:
1 Class c = Class.forName("MyAnnotation");
Then which of the following method invocations on Class c
will return true?
c.isAnnotation()
c.isPrimitive()
c.isInterface()
c.isArray()
@Target
meta-annotation.18.116.21.152