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:
@Override 
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
 . . . 
One of the following type can be used for annotation fields:
  • 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 {... } 

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 Policies for the @Retention Annotation
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 for the @Target Annotation
Element TypesDescription
CONSTRUCTORAnnotation can be applied to constructors
FIELDAnnotation can be applied to class fields or global variables
LOCAL VARIABLESAnnotation can be applied to local variables
LOCAL VARIABLESAnnotation can be applied to local variables
METHODAnnotation can be applied to any method declaration
PACKAGEAnnotation can be applied to package declaration
PARAMETERAnnotation can be applied to method parameters
TYPEAnnotation 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.TYPEElementType.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");
}
}

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("========================================");
  //Retrieves all the global variables/fields defined in the Class
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

Popular posts from this blog

Custom PagingNavigator for SEO friendly URL

Importing / Indexing MySQL data into Solr

The Externalizable Interface