Annotations in Java
Annotations are the tags that can be inserted into a Java programs so that they can be processed by the tools.
In the Java programming language, an annotation is used like a modifier, and it is placed before the annotated item, without a semicolon. The name of each annotation is preceded by an @ symbol.
For Example:
public @interface AnnotationName {
//element declarations
type elementName();
type elementName() default value;
. . .
}
One of the following type can be used for annotation fields:
In above example the SuperClass is explicitly annotated with @InheritedAnno and @SuppressWarning. SubClass has not been explicitly marked with any annotation, however it automatically inherits @InheritedAnno because of the @Inherited meta-annotation.
@Retention: indicates how long the annotations are to be retained. If no retention policy is defined, it defaults to RetentionPolicy.CLASS
@Target: describes the program element on which an annotation is applicable. If no target is defined the annotation can be used on any program element. If target is defined the compiler will enforce specific usage restriction.
Annotated Class
Following code snippet shows the various formats in which an annotation can be annotated.
//Fetches Class Level Annotation information
//Retrieves all the methods defined in the Class
//Checks is CustomAnnotation is Present on the current method
//Retrieves all the global variables/fields defined in the Class
For Example:
@Override
public boolean equals(Object obj){
...
}
public boolean equals(Object obj){
...
}
Annotation Syntax
An annotation is defined by an annotation interface:public @interface AnnotationName {
//element declarations
type elementName();
type elementName() default value;
. . .
}
- All primitives (boolean, char, short, int, long, double)
- String
- Class
- Enum
- Array of any of above types
Meta-Annotations
Meta annotations are annotations that are used to annotate annotations. There are four meta-annotation types that come standard with Java 5:
@Documented: is a marker annotation. Annotation declaration (of the @documented annotation type) will be included in the documentation generated using Javadoc or similar tools.
@Inherited: indicates that an annotation type is inherited by subclasses of annotated class.
@Inherited
public @interface InheritedAnno {
}
@InheritedAnno
@SuppressWaring("unchecked")
public class SuperClass { ... }
public class SubClass extends SuperClass {... }
public @interface InheritedAnno {
}
@InheritedAnno
@SuppressWaring("unchecked")
public class SuperClass { ... }
public class SubClass extends SuperClass {... }
In above example the SuperClass is explicitly annotated with @InheritedAnno and @SuppressWarning. SubClass has not been explicitly marked with any annotation, however it automatically inherits @InheritedAnno because of the @Inherited meta-annotation.
@Retention: indicates how long the annotations are to be retained. If no retention policy is defined, it defaults to RetentionPolicy.CLASS
Retention Policy | Description |
---|---|
SOURCE | Annotations are not included in class files. Annotations like @Deprecated, @SuppressWarning and @Override are used by the compiler at compile time to validate source code. |
CLASS |
Annotations are included in class files, but the virtual machine need not load them. These are parsed by the application servers and other software tools at the time of deployment to generate XMLs, bolierplate code etc.
|
RUNTIME |
Annotations are included in class files and loaded by the virtual machine. You could make your code to behave in a particular way whenever it is called. This can be achieved by the use of reflection API.
|
@Target: describes the program element on which an annotation is applicable. If no target is defined the annotation can be used on any program element. If target is defined the compiler will enforce specific usage restriction.
Element Types | Description |
---|---|
CONSTRUCTOR | Annotation can be applied to constructors |
FIELD | Annotation can be applied to class fields or global variables |
LOCAL VARIABLES | Annotation can be applied to local variables |
LOCAL VARIABLES | Annotation can be applied to local variables |
METHOD | Annotation can be applied to any method declaration |
PACKAGE | Annotation can be applied to package declaration |
PARAMETER | Annotation can be applied to method parameters |
TYPE | Annotation can be applied to Class, interface and Enum declaration |
User Defined Annotation (Custom Annotation)
package learn.java.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.TYPE, ElementType.FIELD})
public @interface CustomAnnotation {
int id() default 0;
String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.TYPE, ElementType.FIELD})
public @interface CustomAnnotation {
int id() default 0;
String value() default "";
}
Annotated Class
Following code snippet shows the various formats in which an annotation can be annotated.
package learn.java.annotation;
@CustomAnnotation(id=111, value="Annotation on Class")
public class AnnotatedClass {
//The order of the elements does not matter
@CustomAnnotation(value="Annotation on globalVar1", id=222)
private int globalVar1;
//If element value is not specified, the default value is used
@CustomAnnotation(value="Annotation on globalVar2")
private float globalVar2;
//Single valued Annotation
@CustomAnnotation("Annotation on globalVar3")
private int globalVar3;
//Marker Annotation
@CustomAnnotation
private int globalVar4;
@CustomAnnotation(id=123)
public void annotatedMethod(){
System.out.println("Annotated method");
}
}
@CustomAnnotation(id=111, value="Annotation on Class")
public class AnnotatedClass {
//The order of the elements does not matter
@CustomAnnotation(value="Annotation on globalVar1", id=222)
private int globalVar1;
//If element value is not specified, the default value is used
@CustomAnnotation(value="Annotation on globalVar2")
private float globalVar2;
//Single valued Annotation
@CustomAnnotation("Annotation on globalVar3")
private int globalVar3;
//Marker Annotation
@CustomAnnotation
private int globalVar4;
@CustomAnnotation(id=123)
public void annotatedMethod(){
System.out.println("Annotated method");
}
}
Making use of Reflection API
package learn.java.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class CustomAnnotationParser {
public static void main(String[] args) {
parseAnnotatedClass();
}
public static void parseAnnotatedClass(){
Class<AnnotatedClass> c = AnnotatedClass.class;
//Fetches Class Level Annotation information
if(c.isAnnotationPresent(CustomAnnotation.class)){
CustomAnnotation anno = c.getAnnotation(CustomAnnotation.class);
System.out.println("Id: "+anno.id());
System.out.println("Value: "+anno.value());
}
System.out.println("==================================");
//Retrieves all the methods defined in the Class
Method[] methods = c.getDeclaredMethods();
for(Method m : methods){
System.out.println("Method Name = "+m.getName());
//Checks is CustomAnnotation is Present on the current method
if(m.isAnnotationPresent(CustomAnnotation.class)){
CustomAnnotation mAnno = m.getAnnotation(CustomAnnotation.class);
System.out.println("Id: "+mAnno.id());
System.out.println("Value: "+mAnno.value());
}
}
System.out.println("========================================");
Field[] fields = c.getDeclaredFields();
for(Field f : fields){
System.out.println("Field Name = "+f.getName());
if(field.isAnnotationPresent(CustomAnnotation.class)){
CustomAnnotation fAnno = f.getAnnotation(CustomAnnotation.class);
System.out.println("Id: "+fieldAnno.id());
System.out.println("Value: "+fieldAnno.value());
}
else{
System.out.println(field.getName()+" is not annotated");
}
System.out.println("==============================");
}
}
}
The above class make use of Java Reflection API to parse the AnnotatedClass and prints the annotated elements values.
Comments
Post a Comment