Overview of Annotations

Annotations are notes for the Java compiler. When you annotate a program element in a source file, you add notes to the Java program elements in that source file. You can annotate Java packages, types (classes, interfaces, enumerated types), constructors, methods, fields, parameters, and local variables. For example, you can annotate a Java class so that any warnings that the javac program would otherwise issue will be suppressed. Or, you can annotate a method that you want to override to ask the compiler to verify that you are really overriding the method, not overloading it. The Java compiler can be instructed to interpret annotations and discard them (so those annotations only live in source files) or include them in resulting Java classes. Those that are included in Java classes may be ignored by the Java virtual machine, or they may be loaded into the virtual machine. The latter type is called runtime-visible and you can use reflection
to inquire about them.

Annotations and Annotation Types

When studying annotations, you will come across these two terms very frequently: annotations and annotation types. To understand their meanings, it is useful to first bear in mind that an annotation type is a special interface type. An annotation is an instance of an annotation type. Just like an interface, an annotation type has a name and members. The information contained in an annotation takes the form of key/value pairs. There can be zero or multiple pairs and each key has a specific type. It can be a String, int, or other Java types. Annotation types with no key/value pairs are called marker annotation types. Those with one key/value pair are often referred to single-value annotation types. Annotations were first added to Java 5, which brought with it, three annotation types: Deprecated Override, and Suppress Warnings. They for example, here is how you use the marker annotation type Deprecated:

@Deprecated
And, this is how you use the second syntax for multi-value annotation type
Author:
@Author(firstName="Ted",lastName="Diong")
There is an exception to this rule. If an annotation type has a single  key/value pair and the name of the key is value, then you can omit the key from the bracket. Therefore, if fictitious annotation type Stage has a single key named value, you can write
@Stage(value=1) or @Stage(1)
Returns a string representation of this annotation, which typically lists all the key/value pairs of this annotation.

Standard Annotations:

Annotations were a new feature in Java 5 and originally there were three standard annotations, all of which are in the java.lang package: Override, Deprecated, and Suppress Warnings.

Override

Override is a marker annotation type that can be applied to a method to indicate to the compiler that the method overrides a method in a superclass. and Child classes. However, you won’t be always this lucky. Sometimes the parent class is buried somewhere in another package. This seemingly trivial error could be fatal because when a client class calls the calculate method on a Child object and passes two floats, the method in the Parent class will be invoked and the wrong result returned. Using the Override annotation type will prevent this kind of mistake. Whenever you want to override a method, declare the Override annotation type before the method:

Ex:-

public class Child extends Parent
 {
    @Override
    public int calculate(int a, int b)
   {
        return (a + 1) * b;
    }
}
This time, the compiler will generate a compile error and you’ll be notified that the calculate method in Child is not overriding the method in the parent class. It is clear that @Override is useful to make sure programmers override a method when they intend to override it, and not overload it.

Deprecated

Deprecated is a marker annotation type that can be applied to a method or a type to indicate that the method or type is deprecated. A deprecated method or type is marked so by the programmer to warn the users of his code that they should not use or override the method or use or extend the type. The reason why a method or a type is marked deprecated is usually because there is a better method or type and the deprecated method or type is retained in the current software version for backward compatibility. For example, the DeprecatedTest class in Ex.1 uses the Deprecated annotation type.

Ex.1: Deprecating a method
package app1;
public class DeprecatedTest
{
   @Deprecated
    public void serve()
   {    }
}
If you use or override a deprecated method, you will get a warning at compile time. For example, EX.2 shows a DeprecatedTest2 class that uses the serve method in DeprecatedTest.

Ex.2: Using a deprecated method
package app1;
public class DeprecatedTest2
{
    public static void main(String[] args)
   {
        DeprecatedTest test = new DeprecatedTest();
        test.serve();
    }
}
Compiling DeprecatedTest2 generates this warning: Note: app1/DeprecatedTest2.java uses or overrides a deprecated


Suppress Warnings:

Suppress Warnings is used, as you must have guessed, to suppress compiler warnings. You can apply @SuppressWarnings to types, constructors, methods, fields, parameters, and local variables. You use it by passing a String array that contains warnings that need to be suppressed. Its syntax is as follows.

                          @SuppressWarnings(value={string-1, ..., string-n})

Where string-1 to string-n indicate the set of warnings to be suppressed. Duplicate and unrecognized warnings will be ignored.The following are valid parameters to @SuppressWarnings:

▪unchecked. Gives more detail for unchecked conversion warnings that are mandated by the Java Language Specification.

▪path. Warns about nonexistent path (classpath, sourcepath, etc) directories.

As an example, the SuppressWarningsTest class in Ex:-.4 uses the SuppressWarnings annotation type to prevent the compiler from issuing unchecked and fallthrough warnings.


Ex 4 Using @SuppressWarnings

package app1;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
@SuppressWarnings(value={"unchecked","serial"})
public class SuppressWarningsTest implements Serializable
{
    public void openFile()
    {
        ArrayList a = new ArrayList();
        File file = new File("X:/java/doc.txt");
    } 
}

Common Annotations:

  ▪ comments. Comments accompanying the generated code. For example, in Ex.5 @Generated is used to annotate a generated class.

Ex.5: Using @Generated
package app18;
import javax.annotation.Generated;
@Generated(value="com.chandrasoftware.robot.CodeGenerator",
        date="2012-11-31", comments="Generated code")
public class GeneratedTest
{
}

Standard Meta-Annotations:

Meta annotations are annotations that annotate annotations. There are four meta-annotation types that can be used to annotate annotations: Documented, Inherited, Retention, and Target. All the four are part of the java.lang.annotation package. This section discusses these annotations
                        types.
                        Documented
Documented is a marker annotation type used to annotate the declaration of an annotation type so that instances of the annotation type will be included in the documentation generated using Javadoc or similar tools.For example, the Override annotation type is not annotated using Documented. As a result, if you use Javadoc to generate a class whose
method is annotated @Override, you will not see any trace of @Override in the resulting document. For instance, Ex.6 shows a OverrideTest2 class that uses @Override to annotate the toString method.

Ex.6: The OverrideTest2 class
package app1;
public class OverrideTest2
{
    @Override
    public String toString()
    {
        return "OverrideTest2";
    }
}

On the other hand, the Deprecated annotation type is annotated @Documented. Recall that the serve method in the DeprecatedTest class in Ex.2 is annotated @Deprecated. Now, if you use Javadoc to generate the documentation for OverrideTest2 the details of the serve method in the documentation will also include @Deprecated, like this: serve
@Deprecated
public void serve()
▪SOURCE. Annotations are to be discarded by the Java compiler.
▪CLASS. Annotations are to be recorded in the class file but not retained by the JVM.           This is the default value.
▪RUNTIME. Annotations are to be retained by the JVM so they can be queried using reflection. For example, the declaration of the SuppressWarnings annotation type is annotated @Retention with the value of SOURCE.

@Retention(value=SOURCE)
public @interface SuppressWarnings

Target:

Target indicates which program element(s) can be annotated using instances of the annotated annotation type. The value of Target is one of the members of the java.lang.annotation.ElementType enum: As an example, the Override annotation type declaration is annotated the following Target annotation, making Override only applicable to method declarations.

@Target(value=METHOD)

You can have multiple values in the Target annotation. For example, this is from the declaration of SuppressWarnings:
@Target(value={TYPE,FIELD, METHOD, PARAMETER,CONSTRUCTOR,
LOCAL_VARIABLE})

Custom Annotation Types:

An annotation type is a Java interface, except that you must add an at sign before the interface keyword when declaring it.

public @interface CustomAnnotation
{
}
Using Custom Annotation Types:

The Author annotation type is like any other Java type. Once you import it into a class or an interface, you can use it simply by writing

@Author(firstName="firstName",lastName="lastName", internalEmployee=true|false)
For example, the Test1 class in Ex.8 is annotated Author.

 Ex.8: A class annotated Author
package app1.custom;
@Author(firstName="John",lastName="Guddell",internalEmployee=true)
public class Test1 {
}
The next subsection “Using Reflection to Query Annotations” shows how the Author annotations can be of good use. Using Reflection to Query Annotations The java.lang.Class class has several methods related to annotations.

public <A extends java.lang.annotation.Annotation> A getAnnotation (Class<A> annotationClass) Returns this element’s annotation for the specified annotation type, if
present.
Otherwise, returns null. public java.lang.annotation.Annotation[] getAnnotations()
Returns all annotations present on this class.

public boolean isAnnotation() Returns true if this class is an annotation type.
public boolean isAnnotationPresent(Class<? Extends
        java.lang.annotation.Annotation> annotationClass)

Indicates whether an annotation for the specified type is present on this class The app1.custom package includes three test classes, Test1, Test2, and Test3, that are annotated Author. Ex.9 shows a test class that employs reflection to query the test classes.
Ex.9: Using reflection to query annotations
package app1.custom;
public class CustomAnnotationTest
{
    public static void printClassInfo(Class c)
    {
        System.out.print(c.getName() + ". ");
        Author author = (Author) c.getAnnotation(Author.class);
        if (author != null)
       {
            System.out.println("Author:" + author.firstName()
                    + " " + author.lastName());
        } else {
            System.out.println("Author unknown");
        }   
    }
    public static void main(String[] args)
    {
        CustomAnnotationTest.printClassInfo(Test1.class);
    }
}

Post a Comment

 
Top