Languages - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Languages arrow An Overview of Java 5's Annotations
An Overview of Java 5's Annotations
By Marcus Zarra

Rate This Article: Add This Article To:

While some of the language enhancements in the latest release of Java are "syntactic sugar," annotations do not fall into that category. Marcus Zarra walks through what annotations are, which ones are built in, and an example of how to use the

An annotation is "a note of explanation or comment added to a text or diagram." In Java, annotations give you the ability to provide hints directly in the source code which can later be used by the compiler, by other parts of the code, or by another tool. Annotations are also referred to as metadata: data about data.

Annotations have existed in Java code for many years, in one form or another. @deprecated is one example of an annotation that the Java compiler itself uses to tag a method as deprecated. The keyword transient is also an annotation used as a hint during serialization. In addition to the built-in annotations, many tools use JavaDoc tags as types of annotation. For example, xDoclet uses JavaDoc tags as hints to built additional source code.

ADVERTISEMENT

The one very important difference between these tags and J2SE 5 Annotations is that the former could only be used at compile time. These tags were not carried on into the compiled bytecode. Instead, J2SE 5 Annotations are available both at compile time and at runtime, giving them some added advantages.

Annotations can be defined by the developer. While it is unlikely that it will be necessary during the normal course of development, defining them is rather straight forward.

A simple example makes these advantages quite clear. First, an annotation called @Test. This annotation is defined as:

@Retention(value=RUNTIME)
@Target(value=METHOD)
public @interface Test {}

In this definition, two built-in annotations are being used. The use of these annotations is detailed below. For now, suffice it to say that @Test is a runtime annotation that tags methods. With this annotation in existence, it is possible to build a class as follows:

public class Foo {
    @Test public static void m1() {}
    public static void m2() {}
    @Test public static void m3() {
        throw new RuntimeException("Boom");
    }
    public static void m4() {}
    @Test public static void m5() {}
    public static void m6() {}
    @Test public static void m7() {
        throw new RuntimeException("Crash");
    }
    public static ovid m8() {}
}

With these tags in place, the class can be tested in a reflective way without having to write the test cases in a separate class:

import java.lang.reflect.*;

public class RunTests {
    public static void main(String args[]) throws Exception {
        int passed = 0;
        int failed = 0;
        for (Method m : Class.forName(args[0]).getMethods()) {
            if (!m.isAnnotationPresent(Test.class)) continue;
            try {
                m.invoke(null);
                ++passed;
            } catch (Throwable t) {
              System.out.printf("Test %s failed: %s %n", m, t.getCause());
              ++failed;
            }
        }
        System.out.printf("Passed: %d, Failed %d%n", passed, failed);
    }
}

This example demonstrates the ability to look for annotations at runtime and act on them accordingly. Here, it is possible to flag methods as test and then run them without having to execute every method on the class or name the method in a specific way. In addition, by using annotations, you gain the benefit of error-checking by the compiler. If you mistype @Test as @Tset, the compiler is happy to let you know about the error, avoiding the needless head-scratching that invariably occurs with an error like that.

Built-In Annotations

In addition to being able to define your own annotations, J2SE 5 "Tiger" comes with several prebuilt annotations. Each is detailed below:

java.lang.Override

@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override {}

java.lang.Override indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.

java.lang.annotation.Deprecated

@Documented
@Retention(value=RUNTIME)
public @interface Deprecated {}

A program element annotated @Deprecated is one that programmers are discouraged from using, typically because using it is dangerous, or because a better alternative exists. Compilers warn when a deprecated program element is used or overridden in non-deprecated code.

java.lang.annotation.Documented

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Documented {}

Indicates that annotations with a type are to be documented by javadoc and similar tools by default. This type should be used to annotate the declarations of types whose annotations affect the use of annotated elements by their clients. If a type declaration is annotated with Documented, its annotations become part of the public API of the annotated elements.

java.lang.annotation.Retention

@Documented
@Retention(value=RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS.

A Target meta-annotation has effect only if the meta-annotated type is use directly for annotation. It has no effect if the meta-annotated type is used as a member type in another annotation type.

java.lang.annotation.Inherited

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited {}

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass is automatically queried for the annotation type. This process is repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query indicates that the class in question has no such annotation.

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Also, this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

java.lang.annotation.Target

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

Indicates the kinds of program element to which an annotation type is applicable. If a Target meta-annotation is not present on an annotation type declaration, the declared type may be used on any program element. If such a meta-annotation is present, the compiler enforces the specified usage restriction.

For example, this meta-annotation indicates that the declared type is itself a meta-annotation type. It can only be used on annotation type declarations:

    @Target(ElementType.ANNOTATION_TYPE)
    public @interface MetaAnnotationType {
       ... 
    }

This meta-annotation indicates that the declared type is intended solely for use as a member type in complex annotation type declarations. It cannot be used to annotate anything directly:

    @Target({}) 
    public @interface MemberType {
        ...
    }

It is a compile-time error for a single ElementType constant to appear more than once in a Target annotation. For example, the following meta-annotation is illegal:

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
    public @interface Bogus {
        ...
    }

java.lang.SuppressWarnings

@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SupressWarnings{}

Indicates that the named compiler warnings should be suppressed in the annotated element (and in all program elements contained in the annotated element). The set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements. For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings are suppressed in the method.

Annotations are a powerful addition to the Java language specification. It will take some time before third-party tools and libraries make full use of them; but as they become more widespread, the power of annotations will become fully realized. Just imagine data objects that define which methods should be persisted and what types of columns should be used, or methods in an application server that define what types of users should be allowed to access them. The future should be very interesting.




Discuss An Overview of Java 5's Annotations
 
>>> Be the FIRST to comment on this article!
 

 
 
>>> More Languages Articles          >>> More By Marcus Zarra
 



Microsoft's Future: A Chat With Their CTO, Barry Briggs

Play Video >

All Videos >

Julia explores the Robotics Studio!

Read now >

Messages to Bill Gates!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.