You have possibly encountered predicaments exactly where you need to have to affiliate metadata (information that describes other information) with classes, procedures, and/or other software features. For illustration, your programming staff may well need to have to discover unfinished classes in a massive software. For each and every unfinished class, the metadata would probable involve the name of the developer dependable for finishing the class and the class’s envisioned completion day.
Before Java five, responses ended up the only versatile mechanism that Java experienced to supply for associating metadata with software features. Nonetheless, responses are a weak decision. Simply because the compiler ignores them, responses are not obtainable at runtime. And even if they ended up obtainable, the textual content would have to be parsed to get hold of crucial information products. Without the need of standardizing how the information products are specified, these information products may well verify unachievable to parse.
Down load the supply code for examples in this Java one zero one tutorial. Established by Jeff Friesen for InfoWorld.
Java five modified every thing by introducing annotations, a common mechanism for associating metadata with many software features. This mechanism consists of four parts:
@interfacemechanism for declaring annotation types.
- Meta-annotation types, which you can use to discover the software features to which an annotation form applies to discover the life time of an annotation (an instance of an annotation form) and a lot more.
- Support for annotation processing by using an extension to the Java Reflection API (to be reviewed in a upcoming report), which you can use to find out a program’s runtime annotations, and a generalized device for processing annotations.
- Typical annotation types.
I’ll describe how to use these parts as we function our way via this report.
Declaring annotation types with @interface
You can declare an annotation form by specifying the
@ symbol immediately adopted by the
interface reserved phrase and an identifier. For illustration, Listing one declares a uncomplicated annotation form that you may well use to annotate thread-harmless code.
general public @interface ThreadSafe
Just after declaring this annotation form, prefix the procedures that you look at thread-harmless with occasions of this form by prepending
@ immediately adopted by the form name to the process headers. Listing two provides a uncomplicated illustration exactly where the
principal() process is annotated
AnnDemo.java (variation one)
general public class AnnDemo @ThreadSafe general public static void principal(String args)
ThreadSafe occasions supply no metadata other than the annotation form name. Nonetheless, you can supply metadata by incorporating features to this form, exactly where an factor is a process header positioned in the annotation type’s system.
As properly as not possessing code bodies, features are issue to the subsequent limitations:
- The process header simply cannot declare parameters.
- The process header simply cannot supply a throws clause.
- The process header’s return form must be a primitive form (e.g.,
java.lang.Course, an enum, an annotation form, or an array of one particular of these types. No other form can be specified for the return form.
As one more illustration, Listing 3 presents a
ToDo annotation form with three features pinpointing a certain coding job, specifying the day when the job is to be concluded, and naming the coder dependable for completing the job.
ToDo.java (variation one)
general public @interface ToDo int id() String finishDate() String coder() default "n/a"
Note that each and every factor declares no parameter(s) or throws clause, has a lawful return form (
String), and terminates with a semicolon. Also, the closing factor reveals that a default return benefit can be specified this benefit is returned when an annotation does not assign a benefit to the factor.
Listing four employs
ToDo to annotate an unfinished class process.
AnnDemo.java (variation two)
general public class AnnDemo general public static void principal(String args) String towns = "New York", "Melbourne", "Beijing", "Moscow", "Paris", "London" form(towns) @ToDo(id = one thousand, finishDate = "ten/ten/2019", coder = "John Doe") static void form(Item objects)
Listing four assigns a metadata merchandise to each and every factor for illustration,
one thousand is assigned to
id. Compared with
finishDate features must be specified in any other case, the compiler will report an error. When
coder isn’t assigned a benefit, it assumes its default
Java provides a specific
String benefit() factor that can be utilised to return a comma-divided list of metadata products. Listing five demonstrates this factor in a refactored variation of
ToDo.java (variation two)
general public @interface ToDo String benefit()
benefit() is an annotation type’s only factor, you really do not have to specify
benefit and the
= assignment operator when assigning a string to this factor. Listing 6 demonstrates the two strategies.
AnnDemo.java (variation 3)
general public class AnnDemo general public static void principal(String args) String towns = "New York", "Melbourne", "Beijing", "Moscow", "Paris", "London" form(towns) @ToDo(benefit = "one thousand,ten/ten/2019,John Doe") static void form(Item objects) @ToDo("one thousand,ten/ten/2019,John Doe") static boolean research(Item objects, Item key) return bogus
Employing meta-annotation types — the problem of versatility
You can annotate types (e.g., classes), procedures, area variables, and a lot more. Nonetheless, this versatility can be problematic. For illustration, you may well want to limit
ToDo to procedures only, but nothing prevents it from staying utilised to annotate other software features, as shown in Listing seven.
AnnDemo.java (variation four)
@ToDo("one thousand,ten/ten/2019,John Doe") general public class AnnDemo general public static void principal(String args) @ToDo(benefit = "one thousand,ten/ten/2019,John Doe") String towns = "New York", "Melbourne", "Beijing", "Moscow", "Paris", "London" form(towns) @ToDo(benefit = "one thousand,ten/ten/2019,John Doe") static void form(Item objects) @ToDo("one thousand,ten/ten/2019,John Doe") static boolean research(Item objects, Item key) return bogus
In Listing seven,
ToDo is also utilised to annotate the
AnnDemo class and
towns area variable. The presence of these faulty annotations may well confuse someone examining your code, or even your possess annotation processing applications. For the times when you need to have to slim an annotation type’s versatility, Java provides the
Concentrate on annotation form in its
Concentrate on is a meta-annotation form — an annotation form whose annotations annotate annotation types, as opposed to a non-meta-annotation form whose annotations annotate software features, these as classes and procedures. It identifies the types of software features to which an annotation form is relevant. These features are discovered by
ElementValue benefit() factor.
java.lang.annotation.ElementType is an enum whose constants describe software features. For illustration,
CONSTRUCTOR applies to constructors and
PARAMETER applies to parameters. Listing eight refactors Listing 5’s
ToDo annotation form to limit it to procedures only.
ToDo.java (variation 3)
import java.lang.annotation.ElementType import java.lang.annotation.Concentrate on @Concentrate on(ElementType.Technique) general public @interface ToDo String benefit()
Specified the refactored
ToDo annotation form, an attempt to compile Listing seven now success in the subsequent error information:
AnnDemo.java:one: error: annotation form not relevant to this kind of declaration @ToDo("one thousand,ten/ten/2019,John Doe") ^ AnnDemo.java:6: error: annotation form not relevant to this kind of declaration @ToDo(benefit="one thousand,ten/ten/2019,John Doe") ^ two faults
Further meta-annotation types
Java five released three further meta-annotation types, which are located in the
Retentionsignifies how extended annotations with the annotated form are to be retained. This type’s affiliated
java.lang.annotation.RetentionPolicyenum declares constants
Course(compiler documents annotations in class file digital device does not keep them to help save memory — default policy),
RUNTIME(compiler documents annotations in class file digital device retains them), and
Source(compiler discards annotations).
Documentedsignifies that occasions of
Documented-annotated annotations are to be documented by
javadocand similar applications.
Inheritedsignifies that an annotation form is mechanically inherited.
Java eight released the
java.lang.annotation.Repeatable meta-annotation form.
Repeatable is utilised to point out that the annotation form whose declaration it (meta-)annotates is repeatable. In other words and phrases, you can implement several annotations from the exact repeatable annotation form to an software factor, as shown here:
@ToDo(benefit = "one thousand,ten/ten/2019,John Doe") @ToDo(benefit = "1001,ten/ten/2019,Kate Doe") static void form(Item objects)
This illustration assumes that
ToDo has been annotated with the
Repeatable annotation form.
Annotations are intended to be processed in any other case, there’s no point in possessing them. Java five prolonged the Reflection API to aid you produce your possess annotation processing applications. For illustration,
Course declares an
Annotation process that returns an array of
java.lang.Annotation occasions describing annotations existing on the factor explained by the
Listing nine presents a uncomplicated software that hundreds a class file, interrogates its procedures for
ToDo annotations, and outputs the parts of each and every located annotation.
import java.lang.replicate.Technique general public class AnnProcDemo general public static void principal(String args) throws Exception if (args.length != one) Process.err.println("use: java AnnProcDemo classfile") return Technique procedures = Course.forName(args).getMethods() for (int i = i < methods.length i++) if (methods[i].isAnnotationPresent(ToDo.class)) ToDo todo = methods[i].getAnnotation(ToDo.class) String components = todo.value().split(",") System.out.printf("ID = %s%n", components) System.out.printf("Finish date = %s%n", components) System.out.printf("Coder = %s%n%n", components)
Just after verifying that accurately one particular command-line argument (pinpointing a class file) has been specified,
principal() hundreds the class file by using
getMethods() to return an array of
java.lang.replicate.Technique objects pinpointing all
general public procedures in the class file, and processes these procedures.
Technique processing commences by invoking
boolean isAnnotationPresent(Course annotationClass) process to decide if the annotation explained by
ToDo.class is existing on the process. If so,
process is known as to get hold of the annotation.
ToDo annotations that are processed are these whose types declare a single
String benefit() factor (see Listing five). Simply because this element’s string-based metadata is comma-divided, it requires to be break up into an array of component values. Each of the three component values is then accessed and output.
Compile this supply code (
javac AnnProcDemo.java). Before you can operate the software, you are going to need to have a suitable class file with
@ToDo annotations on its
general public procedures. For illustration, you could modify Listing 6’s
AnnDemo supply code to involve
general public in its
research() process headers. You will also need to have Listing 10’s
ToDo annotation form, which necessitates the
RUNTIME retention policy.
ToDo.java (variation four)
import java.lang.annotation.ElementType import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy import java.lang.annotation.Concentrate on @Concentrate on(ElementType.Technique) @Retention(RetentionPolicy.RUNTIME) general public @interface ToDo String benefit()
Compile the modified
AnnDemo.java and Listing ten, and execute the subsequent command to process
java AnnProcDemo AnnDemo
If all goes properly, you should really observe the subsequent output:
ID = one thousand Finish day = ten/ten/2019 Coder = John Doe ID = one thousand Finish day = ten/ten/2019 Coder = John Doe
Typical annotation types
Inherited, Java five released
java.lang.SuppressWarnings. These three annotation types are created to be utilised in a compiler context only, which is why their retention insurance policies are established to