Type Annotations & Repeating Annotations in Java

Type Annotations & Repeating Annotations in JavaRoland HewageBlockedUnblockFollowFollowingApr 18Type AnnotationsBefore the Java SE 8 release, annotations could only be applied to declarations.

As of the Java SE 8 release, annotations can also be applied to any type use.

This means that annotations can be used anywhere you use a type.

A few examples of where types are used are class instance creation expressions (new), casts, implements clauses, and throws clauses.

Class instance creation expression:new @Interned MyObject();Type cast:myString = (@NonNull String) str;implements clause:class UnmodifiableList<T> implements @Readonly List<@Readonly T> { .

}Thrown exception declaration:void monitorTemperature() throws @Critical TemperatureException { .

}This form of annotation is called a type annotation.

Type annotations were created to support improved analysis of Java programs way of ensuring stronger type checking.

The Java SE 8 release does not provide a type checking framework, but it allows you to write (or download) a type checking framework that is implemented as one or more pluggable modules that are used in conjunction with the Java compiler.

For example, you want to ensure that a particular variable in your program is never assigned to null; you want to avoid triggering a NullPointerException.

You can write a custom plug-in to check for this.

You would then modify your code to annotate that particular variable, indicating that it is never assigned to null.

The variable declaration might look like this:@NonNull String str;When you compile the code, including the NonNull module at the command line, the compiler prints a warning if it detects a potential problem, allowing you to modify the code to avoid the error.

After you correct the code to remove all warnings, this particular error will not occur when the program runs.

You can use multiple type-checking modules where each module checks for a different kind of error.

In this way, you can build on top of the Java type system, adding specific checks when and where you want them.

With the judicious use of type annotations and the presence of pluggable type checkers, you can write code that is stronger and less prone to error.

In many cases, you do not have to write your own type checking modules.

There are third parties who have done the work for you.

For example, you might want to take advantage of the Checker Framework created by the University of Washington.

This framework includes a NonNull module, as well as a regular expression module, and a mutex lock module.

For more information, see the Checker Framework.

Repeating AnnotationsThere are some situations where you want to apply the same annotation to a declaration or type use.

As of the Java SE 8 release, repeating annotations enable you to do this.

For example, you are writing code to use a timer service that enables you to run a method at a given time or on a certain schedule, similar to the UNIX cron service.

Now you want to set a timer to run a method, doPeriodicCleanup, on the last day of the month and on every Friday at 11:00 p.

m.

To set the timer to run, create an @Schedule annotation and apply it twice to the doPeriodicCleanupmethod.

The first use specifies the last day of the month and the second specifies Friday at 11p.

m.

, as shown in the following code example:@Schedule(dayOfMonth="last")@Schedule(dayOfWeek="Fri", hour="23")public void doPeriodicCleanup() { .

}The previous example applies an annotation to a method.

You can repeat an annotation anywhere that you would use a standard annotation.

For example, you have a class for handling unauthorized access exceptions.

You annotate the class with one @Alert annotation for managers and another for admins:@Alert(role="Manager")@Alert(role="Administrator")public class UnauthorizedAccessException extends SecurityException { .

}For compatibility reasons, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler.

In order for the compiler to do this, two declarations are required in your code.

Step 1: Declare a Repeatable Annotation TypeThe annotation type must be marked with the @Repeatable meta-annotation.

The following example defines a custom @Schedule repeatable annotation type:import java.

lang.

annotation.

Repeatable;@Repeatable(Schedules.

class)public @interface Schedule { String dayOfMonth() default "first"; String dayOfWeek() default "Mon"; int hour() default 12;}The value of the @Repeatable meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations.

In this example, the containing annotation type is Schedules, so repeating @Schedule annotations is stored in an @Schedules annotation.

Applying the same annotation to a declaration without first declaring it to be repeatable results in a compile-time error.

Step 2: Declare the Containing Annotation TypeThe containing annotation type must have a value element with an array type.

The component type of the array type must be the repeatable annotation type.

The declaration for the Schedulescontaining annotation type is the following:public @interface Schedules { Schedule[] value();}Retrieving AnnotationsThere are several methods available in the Reflection API that can be used to retrieve annotations.

The behavior of the methods that return a single annotation, such asAnnotatedElement.

getAnnotation(Class<T>), are unchanged in that they only return a single annotation if one annotation of the requested type is present.

If more than one annotation of the requested type is present, you can obtain them by first getting their container annotation.

In this way, legacy code continues to work.

Other methods were introduced in Java SE 8 that scan through the container annotation to return multiple annotations at once, such as AnnotatedElement.

getAnnotationsByType(Class<T>).

See the AnnotatedElement class specification for information on all of the available methods.

Design ConsiderationsWhen designing an annotation type, you must consider the cardinality of annotations of that type.

It is now possible to use an annotation zero times, once, or, if the annotation’s type is marked as @Repeatable, more than once.

It is also possible to restrict where an annotation type can be used by using the @Target meta-annotation.

For example, you can create a repeatable annotation type that can only be used on methods and fields.

It is important to design your annotation type carefully to ensure that the programmer using the annotation finds it to be as flexible and powerful as possible.

.. More details

Leave a Reply