articles

Home / DeveloperSection / Articles / Annotations in Java: @Target and @Retention

Annotations in Java: @Target and @Retention

Jonas Stuart22001 28-May-2016
In the previous posts we learn how to declare:

·     Marker Annotations

·      Single Value Annotations

·      Multi-value annotations

But, in this post we learn how to annotate an annotation using few more annotation specifically meant for this purpose.

Annotating an Annotation

When we create our own annotations, their purpose may not be always self-evident. We might want to supply some sort of metadata (another java annotation) on our newly created annotation type so that a tool can introspect and reveal this intended functionality or a compiler can enforce the intended functionality during compilation.

The Java language defines four annotation types for this purpose:

·    Target

·     Retention

·     Documentation

·     Inherited

These are called meta-annotations and are used for annotating your annotations. We discuss @Target annotation in detail here.

The Target Annotation

The Target annotation specifies which elements of our code can have annotations of the defined type. A concrete example will help explain this concept. Add the Target annotation to the Task annotation we defined earlier in the last post, as shown here:

@Target(ElementType.METHOD)
@interface Task {
String description();
...
}

 

Now, the Task annotation can only be applied to a method. Let’s verify this. Modify the CustomAnnotation class defined earlier to add a private taxID field. Apply the Task annotation to this field. The modified class definition is shown here:

public class CustomAnnotation {
            @Task(description = "Assign ID",
            estimatedHours = 0,
            additionalNote = "The IDs are available from IRS")
            private int taxID;
           @WorkInProgress
           @Task(description = "Implement tax computations",
           estimatedHours = 50,
           additionalNote = "This implementation is critical for the final launch")
            public static float ComputeTax(float amount, float rate) {
                       return 0;
         }

}

 

When we compile this code, the compiler throws an error indicating that the annotation type is not applicable to this kind of declaration, where you have defined the taxID field. The application of the Task annotation on the ComputeTax method compiles without errors.

Here are the other types of targets that can be specified in place of ElementType.METHOD:

·     ElementType.TYPE—Can be applied to any element of a class

·     ElementType.FIELDCan be applied to a field

·     ElementType.PARAMETERCan be applied to method parameters

·     ElementType.CONSTRUCTORCan be applied to constructors

·     ElementType.LOCAL_VARIABLE—Can be applied to local variables

·     ElementType.ANNOTATION_TYPEIndicates that the declared type itself is an annotation type

The Retention Annotation

This annotation sets the visibility of the annotation to which it is applied. The visibility can be set for three different levels:

·         Compilers

·         Tools

·         Runtime.

The visibility is set with the help of another built-in annotation called @Retention. We set the annotation visibility using the following syntax:

@Retention(RetentionPolicy.RUNTIME)
@interface Task {


As shown, the @Retention annotation precedes the annotation declaration. It has one field that is set to a predefined constant of the RententionPolicy enumeration.

The RetentionPolicy enumeration defines three constants:

·         SOURCE

·         CLASS

·         RUNTIME.

If we select SOURCE, the annotation will be visible to the compiler and will not be available in the .class files and to the runtime. The compiler uses this annotation to detect errors and suppress warnings. After its use, the compiler discards the annotation.

 When we use the CLASS identifier, the annotation will be recorded in the .class file; however, the virtual machine (VM) need not retain it at runtime. This is the default policy.

Lastly, if we use the RUNTIME identifier, not only is the annotation recorded in the .class file, but it is also made available to the runtime by the JVM.

Thus, a running program can introspect this annotation and display its values to the user. This feature is demonstrated with the help of example in the next post.


Updated 24-Nov-2019

Leave Comment

Comments

Liked By