Go4Expert

Go4Expert (http://www.go4expert.com/)
-   Java (http://www.go4expert.com/articles/java-tutorials/)
-   -   Java Annotations (http://www.go4expert.com/articles/java-annotations-t30118/)

AbdulMazed 23May2014 21:54

Java Annotations
 
Since JDK version 5.0, a new mechanism was introduced in Java that enables us to include additional information (known as metadata) directly into the java source code. This information is termed as Annotations. In English dictionary, Annotation means “a note by way of explanation or comment added to a text or diagram”. An annotation is a syntactic metadata that can be added to Java Source code, without directly affecting the execution of the code. It consists of syntax for declaring annotation types, a syntax for annotating declarations, APIs for reading annotations, a class file representation for annotations, and an annotation processing tool.

Prior to JDK version 5.0, the Java platform had a few ad-hoc annotation mechanisms. For example, the transient modifier is a type of ad-hoc annotation that indicates JVM to ignore a field containing the modifier at the time of serialization, and the @deprecated Javadoc tag indicates that the method is obsolete. A provisional interface for compile-time annotation processing was provided by the apt tool in JDK version 5.0, and was formalized through JSR-269. Later it was integrated into the javac compiler in version 6.0.

Uses of Java Annotations



Annotations are used for various purposes:
  • Information for the compiler — there are some annotations that the compiler uses to detect errors, generate warnings like deprecated or suppress warnings.
  • Compile-time and deployment-time processing — there are some annotations that software tools use for processing metadata to generate code, XML files, and so forth. EJB, Spring, Hibernate and JSF use these annotations to replace XML configuration files.
  • Runtime processing — there are some annotations that are available to be examined at runtime via Java reflection.

Creating an Annotation



An annotation type is declared as a special kind of interface. So, the interface keyword is preceded by at-sign (@) (@ = AT as in Annotation Type).
Code:

// Simple annotation type
public @interface Description {
        String author();
        double since() default 1.0;
}

The above code tells the compiler that an annotation type has been declared. Now we can use it in any of our classes. The annotation type contains two elements author() and since() which looks similar to methods. They can also define optional values.

Note:
  • An annotation cannot include an extends clause.
  • All annotation types automatically extend the java.lang.Annotation interface.
  • It also specifies annotationType(), which returns a Class object that represents the invoking annotation.
  • Method declarations must not have any parameters or a throws clause.
    vReturn types of methods are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types.
  • Any type of declaration can have an annotation associated with it, e.g. classes, methods, fields, parameters, and enum constants.
  • An annotation can also be annotated.
Once the annotation type is defined, any method can be annotated with filled in values, like this:

Code:

//Annotating a method
@Description(author = “Mr. Bean”, since = 1.0)
public void method() {
        System.out.println(“Inside method...”);
}

@Description(author = “Mr. Jack”)
public void display() {
        System.out.println(“Inside display...”);
}

The since() element has a default value specified in the Annotation declaration. So, this element can be ignored while annotating the display() method above.

Meta-Annotations



Annotations that apply to other annotations are called meta-annotations. That means if we provide any meta-information to an annotation type, then it is called meta-annotations. There are several meta-annotation types mentioned below:

@Retention

The @Retention annotation determines at what point an annotation is discarded. There are three possible values of retention policies:
  • RetentionPolicy.SOURCE – which means the annotation is retained only in the source file and discarded during compilation. Here the annotation is present in the .java file but not present in the .class file.
  • RetentionPolicy.CLASS – which means the annotation is retained by the compiler at compile time, but is ignored by the JVM. Here the annotation is present in the .class file but JVM ignores it. This is the default retention policy if no retention policy is specified for an annotation.
  • RetentionPolicy.RUNTIME – which means the annotation is retained by the compiler and JVM so that it can be used at runtime via reflection. The runtime retention offers the greatest annotation persistence.

@Target

The @Target annotation specifies the types of declarations to which an annotation can be applied. A target annotation specifies one or more of the following element types as its values:
  • ElementType.ANNOTATION_TYPE for annotation type.
  • ElementType.CONSTRUCTOR for constructor.
  • ElementType.FIELD for field or property.
  • ElementType.LOCAL_VARIABLE for local variable.
  • ElementType.METHOD for method-level annotation.
  • ElementType.PACKAGE for package declaration.
  • ElementType.PARAMETER for parameters of a method.
  • ElementType.TYPE for any element of a class, i.e. class, interface or enumeration.
For example, following statement can be used to specify that an annotation applies only to fields and local variables:

@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE})

@Documented

The @Documented annotation specifies whether the Javadoc tool should document the annotations for the classes using the custom annotation. By default, the annotations are not documented in the Javadoc.

@Inherited

The @Inherited annotation specifies the annotation for a superclass be inherited by the subclass. This means that when a class is annotated with an annotation type having @Inherited annotation, then its subclasses will inherit the annotation of the superclass. This is only applicable to class declaration. By default, it is not true.

Built-in Annotations



Java provides a few built-in annotations as part of the java.lang package. These are:

@Override

The @Override annotation is used only on methods to inform the compiler that the method annotated with this annotation must override a method from its superclass. If a method marked with @Override fails to override a method in one of its superclasses, the compiler generates an error. Though not necessary, it is a good idea to use it.

@Deprecated

The @Deprecated annotation is used to mark a class, method or field as deprecated in order to inform the compiler that the marked element is obsolete and should no longer be used or should be replaced by a newer form. If any program uses a method, class or field marked as deprecated, the compiler generates a warning. If the @Deprecated annotation is used, it is better to use the corresponding @deprecated JavaDoc symbol in its Javadoc comments to notify the programmer that the class, method or field is deprecated, and an alternative one should be used instead.

@SuppressWarnings

The @SuppressWarnings annotation informs the compiler to suppress the warnings for a given method. For example, if a deprecated method is used in another method, the compiler usually generates a warning. However, @SuppressWarnings causes the warning to be suppressed by the compiler.

The Java Language Specification lists two categories: deprecation and unchecked. The unchecked warning can occur when interfacing with legacy code written before the advent of generics. The deprecation warning can occur if a deprecated method, class or field is used. To suppress multiple categories of warnings, use the following syntax:
@SuppressWarnings({“unchecked”, “deprecation”})

Marker Annotations



Marker annotations are special kind of annotations similar to marker interface meaning they do not have any members/elements. Its sole purpose is to mark a declaration. This annotation can be used to check at runtime whether a class, method or field contains a marker annotation by using the method isAnnotationPresent() defined in java.lang.reflect.AnnotatedElement interface. The AnnotatedElement interface allows annotation to be read through Reflections. Following code shows an example of marker interface.

Code:

//Marker annotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MarkMe {
}

//Using the marker annotation in a method
@MarkMe
public void callMethod() {
        System.out.println(“Inside callMethod...”);
}

Note that the parenthesis () has been omitted which is permissible in Marker annotations.

Single Element Annotations



A single element annotation contains only one element. It works like a normal annotation except that it allows a shorthand form of specifying the value of the element. The name of the element in this annotation must be value. While using this annotation, the name of the element can be omitted. Below is an example that creates a single element annotation:
Code:

//Single element Annotation
public @interface Author {
        String value();
}

// Annotating a method with single element annotation
@Author(“Mr. Bean”)
public void display() {
        System.out.println(“Inside display method...”);
}

Note that the value = is not needed.
We can use the single value syntax when applying an annotation that has other members, but those other members must all have default values. For example, the following annotation has year element containing a default value.

Code:

// Annotation containing a value element and another element having default value.
public @interface Copyright {
        String value();
        int year() default 2014;
}

// Using the annotation as single element annotation syntax
// Here value = “ABC Company” and year = 2014
@Copyright(“ABC Company”)
public void doSomething() {
        System.out.println(“Done!”);
}

// Using the annotation to provide values to all elements
@Copyright(value = “ABC Company”, year = 2013)
public void doSomething(String user) {
        System.out.println(“Done!” + user);
}

Using Reflections to process Annotation



If an annotation has a RUNTIME retention policy, the Java compiler conditionally stores the annotation metadata in the class file. JVM can look for the metadata to determine how to interact with the program. A Java programmer can write custom code using reflections to process the annotation. The methods like getAnnotation(), getAnnotations() and isAnnotationPresent() present in java.lang.reflect.AnnotatedElement interface provide a way to retrieve the annotation details reflectively.

This interface is implemented by the Java reflection classes including Class, Constructor, Field, Method and Package. The below code shows a full program that processes annotations using reflection:

Code:

package example.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Documented
@interface MarkMe {

}

@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Copyright {
        String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Description {
        String value();
        double since() default 1.0;
}

@Copyright("ABC company")
public class AnnotationExample {

        @Description(value = "Display with arguments", since = 2.0)
        public void display(String user) {
                System.out.println("Hello " + user);
        }

        @Description("Display without arguments")
        @Deprecated
        public void display() {
                System.out.println("Hello friends!");
        }

        @MarkMe
        public void markedMethod() {
                System.out.println("This method contains marker annotation");
        }

        @Description("Process annotations")
        public void processAnnotation() {
                display();
                try {
                        Class<AnnotationExample> clazz = AnnotationExample.class;
                        Copyright copyAnno = clazz.getAnnotation(Copyright.class);
                        System.out.println("Copyright annotation value for class '" + clazz + "' : " + copyAnno.value());
                        for (Method method : clazz.getMethods()) {
                                if (method.isAnnotationPresent(MarkMe.class)) {
                                        System.out.println("Method '" + method.getName() + "' is annotated with Marker annotation");
                                }
                                for (Annotation annotation : method.getDeclaredAnnotations()) {
                                        System.out.println("Annotation in Method '" + method.getName() + "' : " + annotation);
                                }
                                Description methAnno = method.getAnnotation(Description.class);
                                if (methAnno != null) {
                                        System.out.println("@Description annotation values for method '" + method.getName()
                                                        + "' : value: " + methAnno.value() + ", since: " + methAnno.since());
                                }
                        }
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
        }

        /**
        * @param args
        */
        public static void main(String[] args) {
                AnnotationExample annoExample = new AnnotationExample();
                annoExample.processAnnotation();
        }

}

The output:

http://imgs.g4estatic.com/java/annotations/output.png

References

  1. Java 5.0 SE Tutorial: http://docs.oracle.com/javase/tutori...ons/index.html
  2. Wikipedia: http://en.wikipedia.org/wiki/Java_annotation
  3. Java Complete Reference: Seventh Edition by Herbert Schildt
  4. Wikibooks: http://en.wikibooks.org/wiki/Java_Pr...s/Introduction


All times are GMT +5.5. The time now is 05:54.