The article focuses more on beginners, or those who have not yet worked with this mechanism in the language. I will try to tell what it is, why they are needed, and how you can create convenient annotations for yourself.
Annotations are descriptors that are included in the text of the program, and are used to store the metadata of the program code required at different stages of the program’s life cycle.
Information stored in annotations can be used by appropriate handlers to create the necessary auxiliary files or to mark classes, fields, etc.
Syntax
Annotation is given by the description of the corresponding interface.
For example:
import java.lang.annotation.*; @Target(value=ElementType.FIELD) @Retention(value= RetentionPolicy.RUNTIME) public @interface Name { String name(); String type() default “string”; }
')
As you can see from the example above, the annotation is defined by the description with the
interface keyword and can include several fields that can be specified as mandatory and not mandatory. In the latter case, the default value of the field is substituted.
It is also clear from the example that the annotation itself can be marked with several annotations.
We will understand for a start, what can mark your own annotation, and why.
The
@Retention annotation allows
you to specify the annotation life cycle: it will be present only in the source code, in the compiled file, or it will also be visible during execution. The choice of the desired type depends on how you want to use the annotation, for example, to generate something incidental from the source codes, or in the process of performing knocking to the class through reflection.
The
@Target annotation indicates that we can mark this annotation, it can be a field, a method, a type, etc.
The
@Documented annotation indicates that annotation marked in this way should be added to the javadoc of the field / method, etc.
For example, a class that is annotated without @Documented will look like this:
public class TestClass extends java.lang.Object
And if in the description of the annotation add @Documented, we get:
@ControlledObject(name="name") public class TestClass extends java.lang.Object
The
@Inherited annotation marks an annotation that will be inherited by a descendant of a class marked with such an annotation.
For example, let's make a couple of annotations and mark the class with them.
@Inherited @interface PublicAnnotate { } @interface PrivateAnnotate { } @PublicAnnotate @PrivateAnnotate class ParentClass { } class ChildClass extends ParentClass { }
The ChildClass class inherits only the PublicAnnotate annotation from the parent class.
An example of its annotations.
Now let's try to write a working example using annotations.
Imagine that we have some self-made project that receives a class at the entrance, which is specially anchored so that the project can manage the life cycle of objects of this class, and let there be StartObject, StopObject annotations to describe the class methods, and ControlledObject to describe the class itself. class. The last annotation will give another name field, the path is stored there supposedly name for the search.
Annotations will look like this:
@Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StartObject { } @Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StopObject { } @Target(value=ElementType.TYPE) @Retention(value= RetentionPolicy.RUNTIME) public @interface ControlledObject { String name(); }
We write a module that checks whether the class is suitable for loading into our hypothetical project or not.
First we define the class to be checked.
@ControlledObject(name="biscuits") public class Cookies { @StartObject public void createCookie(){
In order to work with a class, you must first load the class into the application context. We use:
Class cl = Class.forName("org.annotate.test.classes.Cookies");
Further, through the mechanism of reflection, we get access to the fields and annotations of the class.
Check the presence of annotated methods in the class and annotations on the class itself:
if(!cl.isAnnotationPresent(ControlledObject.class)){ System.err.println("no annotation"); } else { System.out.println("class annotated ; name - " + cl.getAnnotation(ControlledObject.class)); } boolean hasStart=false; boolean hasStop=false; Method[] method = cl.getMethods(); for(Method md: method){ if(md.isAnnotationPresent(StartObject.class)) {hasStart=true;} if(md.isAnnotationPresent(StopObject.class)) {hasStop=true;} if(hasStart && hasStop){break;} } System.out.println("Start annotaton - " + hasStart + "; Stop annotation - " + hasStop );
Running, at the output we get:
Start annotaton - true; Stop annotation - true.
If you try to remove one of the annotations, the output will report non-compliance.
Total
I hope I was able to show that annotations provide ample opportunities for working with program code, and it makes sense not only to use standard annotations of the language, but also to facilitate your life by creating annotations to fit your needs.
I can recommend this mechanism in more detail in the book
“Java 2. Library of a Professional, Volume 2. Programming Subtleties” by Kay S. Horstmann, Gary Cornell , or on the oracle website, which also has detailed tutorials.