Using Meta Annotations in Annotation Type Declarations

Each of the Override, Deprecated, and SuppressWarnings annotation types is itself annotated with meta-annotations (annotations that annotate annotation types). For example, Listing 5-18 shows you that the SuppressWarnings annotation type is annotated with two meta-annotations.

Listing 5-18. The annotated SuppressWarnings type declaration

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

public @interface SuppressWarnings

The Target annotation type, which is located in the java.lang.annotation package, identifies the kinds of application elements to which an annotation type applies. @Target indicates that @SuppressWarnings annotations can be used to annotate types, fields, methods, parameters, constructors, and local variables.

Each of TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, and LOCAL_VARIABLE is a member of the ElementType enum, which is also located in the java.lang.annotation package.

The { and } characters surrounding the comma-separated list of values assigned to Target's value() element signify an array—value()'s return type is String[]. Although these braces are necessary (unless the array consists of one item), value= could be omitted when initializing @Target because Target declares only a value() element.

The Retention annotation type, which is located in the java.lang.annotation package, identifies the retention (also known as lifetime) of an annotation type's annotations. @Retention indicates that @SuppressWarnings annotations have a lifetime that is limited to source code—they do not exist after compilation.

SOURCE is one of the members of the RetentionPolicy enum (located in the java.lang.annotation package). The other members are CLASS and RUNTIME. These three members specify the following retention policies:

■ CLASS: The compiler records annotations in the classfile, but the virtual machine does not retain them (to save memory space). This policy is the default.

■ RUNTIME: The compiler records annotations in the classfile, and the virtual machine retains them so that they can be read via the Reflection API (discussed in Chapter 7) at runtime.

■ SOURCE: The compiler discards annotations after using them.

There are two problems with the Stub annotation type shown in Listings 5-13 and 5-15. First, the lack of an @Target meta-annotation means that you can annotate any application element @Stub. However, this annotation only makes sense when applied to methods and constructors. Check out Listing 5-19.

Listing 5-19. Annotating undesirable application elements

@Stub("1,10/21/2010,unassigned")

public class Deck {

@Stub("2,10/21/2010,unassigned")

private Card[] cardsRemaining; @Stub("3,10/21/2010,unassigned")

@Stub("4,10/21/2010,unassigned")

public void shuffle() {

@Stub("5,10/21/2010,unassigned")

public Card[] deal(@Stub("5,10/21/2010,unassigned") int ncards) {

return null;

Listing 5-19 uses @Stub to annotate the Deck class, the cardsRemaining field, and the ncards parameter in addition to annotating the constructor and the two methods. The first three application elements are inappropriate to annotate because they are not stubs.

You can fix this problem by prefixing the Stub annotation type declaration with @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) so that Stub only applies to methods and constructors. After doing this, the Java SE 6u16 javac compiler tool will output the following error messages when you attempt to compile Listing 5-19:

Deck.java:1: annotation type not applicable to this kind of declaration

@Stub("1,10/21/2010,unassigned")

Deck.java:4: annotation type not applicable to this kind of declaration @Stub("2,10/21/2010,unassigned")

Deck.java:15: annotation type not applicable to this kind of declaration public Card[] deal(@Stub("5,10/21/2010,unassigned") int ncards)

3 errors

The second problem is that the default CLASS retention policy makes it impossible to process @Stub annotations at runtime. You can fix this problem by prefixing the Stub type declaration with @Retention(RetentionPolicy.RUNTIME).

Listing 5-20 presents the Stub annotation type with the desired @Target and @Retention meta-annotations.

Listing 5-20. A revamped Stub annotation type

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME)

public ^interface Stub {

String value();

NOTE: Java also provides Documented and Inherited meta-annotation types in the java.lang.annotation package. Instances of @Documented-annotated annotation types are to be documented by javadoc and similar tools.

Instances of @Inherited-annotated annotation types are automatically inherited. According to Inherited's Java documentation, if "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 will automatically be queried for the annotation type. This process will be 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 will indicate that the class in question has no such annotation."

Was this article helpful?

0 0

Post a comment