Reference Link: 6212969
Java custom Annotations (Target,retention,documented,inherit)
Define your own annotation types
By adding a small syntax (Tiger adds a lot of syntax constructs), the Java language supports a new type-the annotation type (annotation type) . Note types look like ordinary classes, but have some unique properties. The most obvious point is that you can annotate other Java code in a class as a symbol ( @
). I'll take a step-by-step description of the process.
@interface statement
There are many similarities between defining a new annotation type and creating an interface, except that interface
you have a symbol before the keyword @
. An example of the simplest annotation type is given in Listing 1:
Listing 1. Very simple annotation type
Package com.oreilly.tiger.ch06; /** * Marker annotation to indicate a method or class * is still in progress. */ Public @interface InProgress {} |
The meaning of Listing 1 is very obvious. If you compile this annotation type and are sure that it is in the classpath, you can use it in your own source code method to indicate that a method or class is still in process, as shown in Listing 2:
Listing 2. Use a custom annotation type
@com. oreilly.tiger.ch06.InProgress public void Calculateinterest (float amount, float rate) { Need to finish this method later } |
The annotation type shown in Listing 1 is used in exactly the same way as the built-in annotation type, except that the name and package are used to indicate a custom comment. Of course, the general Java rules still apply, and you can import that annotation type and use it directly to @InProgress
reference it.
|
Don't miss out on another part of this series
Be sure to read "part 1th" of this article series, which describes the comments in Java 5.0. |
|
Add Member
The basic usage shown above is far from robust enough. You must remember that the note type can have member variables (see Resources), as mentioned in part 1th. This is very useful, especially when you are ready to use annotations as more complex metadata, rather than just using it as the original document. Code analysis tools like to process a lot of information, and custom annotations can provide this kind of information.
The data members in the annotation type are set to work with limited information. You do not need to define the methods of access and modification separately after you define the data members. Instead, you only need to define a method that names it with the name of the member. The data type should be the type of the method's return value. Listing 3 is a concrete example that clarifies some of the more ambiguous requirements:
Listing 3. Add members to a comment type
Package com.oreilly.tiger.ch06; /** * Annotation type to indicate a task still needs to be * completed. */ Public @interface TODO { String value (); } |
Although Listing 3 looks strange, this is the format required by the annotation type. Listing 3 defines a value
string named the type of the annotation that can accept it. Then, you can use the annotation type as in Listing 4:
Listing 4. Use annotation types with member values
@com. oreilly.tiger.ch06.InProgress @TODO ("Figure out the amount of interest per month") public void Calculateinterest (float amount, float rate) { Need to finish this method later } |
There are also not many tricks here. Listing 4 assumes com.oreilly.tiger.ch06.TODO
that the comments in the source code do not require a package-masterpiece prefix. Also, note that the shorthand method in Listing 4 is to provide the value ("Figure out the amount of interest per month")
directly to the comment without specifying the member variable name. Listing 4 and listing 5 are equivalent, and the latter does not take the shorthand form:
Listing 5. The "extended" version of listing 4
@com. oreilly.tiger.ch06.InProgress @TODO (value= "figure out the amount of interest per month") public void Calculateinterest (float amount, float rate) { Need to finish this method later } |
Of course, as coders, we don't want to mix with this "extended" version. Note, however, that shorthand can be used only if the annotation type has only one member variable and the variable name is value
. If this condition is not met, then this feature cannot be exploited.
Set default values
So far, you've got a good starting point, but to be perfect, there's a long way to go. As you might have thought, the next step is to set a default value for the comment. Setting the default value is a good idea if you want the user to specify some values, but only if the values are different from the default values. Listing 6 TODO
illustrates this concept and its implementation with another custom comment-a full-featured version of the annotation type from Listing 4:
Listing 6. Note Types with default values
Package com.oreilly.tiger.ch06; Public @interface Grouptodo { public enum Severity {CRITICAL, IMPORTANT, TRIVIAL, documentation}; Default severity.important; String item (); String AssignedTo (); String dateassigned (); }
|
GroupTODO
several new variables have been added to the annotation type in Listing 6. Because the member variable of the annotation type is not one, naming a variable value
has no meaning. As long as there are more than one member variable, you should name it as accurately as possible. Because it is not possible to benefit from the shorthand shown in Listing 5, you need to create a comment type that is slightly more verbose, but easier to understand.
Another new feature that appears in Listing 6 is that the annotation type defines its own enumeration (the enumeration, enumeration, commonly known as enums , is another new feature of Java 5. It doesn't make much of a difference, especially for annotation types. Then, listing 6 uses the newly defined enumeration as the type of a member variable.
Finally, go back to our topic-the default value. The process of establishing a default value is trivial, you need to add a keyword after the member declaration default
, and then provide the default value. As you expected, the type of the default value must be exactly the same as the type of the member variable declaration. Again, this is not rocket science, but a lexical mutation. Listing 7 shows a comment in a specific application GroupTODO
where no member is specified severity
:
Listing 7. Use default values
@com. oreilly.tiger.ch06.InProgress @GroupTODO ( Item= "figure out the amount of interest per month", assignedto= "Brett McLaughlin", Dateassigned= "08/04/2004" ) Public void Calculateinterest (float amount, float rate) { Need to finish this method later } |
The same comment is used in Listing 8, but this time severity
the value is given:
Listing 8. Overwrite default values
@com. oreilly.tiger.ch06.InProgress @GroupTODO ( Severity=grouptodo.severity.documentation, Item= "need to explain how this rather unusual method works", assignedto= "Jon Stevens", Dateassigned= "07/30/2004" ) Public void Reallyconfusingmethod (int codepoint) { Really weird code implementation } |
Comments on annotations
Before concluding the discussion about annotations (at least in this series), I would like to briefly discuss the comments of the annotations. The predefined annotation types that are touched in part 1th have predefined purposes. However, the purpose of annotation types is not always obvious when writing your own annotation types. In addition to the basic documentation, you may want to write a type for a particular member type or for a set of member types. This requires that you provide some kind of metadata for the annotation type so that the compiler can guarantee that annotations are used as intended.
Of course, the first thing to think about is the metadata form of the Java language selection--comments. You can annotate your comments with 4 predefined annotation types called meta comments . I will describe each of these 4 types.
Specify target
The most obvious meta-comment is what program elements are allowed to have a defined annotation type. Unsurprisingly, such meta-annotations are called Target
. But before you know how to use Target
it, you also need to recognize another class, which is called ElementType
, which is actually an enumeration. This enumeration defines the different program elements that the annotation type can apply. Listing 9 shows the complete ElementType
enumeration:
Listing 9. ElementType Enumeration
Package java.lang.annotation; public enum ElementType { type,//Class, interface, or enum (but not annotation) field,//Field (including enumerated values) method,//Method (does not include constructors) parameter,//Method PARAMETER constructor,//CONSTRUCTOR local_variable,//Local VARIABLE or catch clause annotation_type,//ANNOTATION Types (meta-annotations) package//Java Package } |
The enumeration values in Listing 9 are very clear, and you can analyze the target of their application (through subsequent annotations) yourself. Target
when using meta-annotations, you must provide at least one of these enumeration values and indicate which program elements the comment can be applied to. Listing 10 illustrates Target
the use of:
Listing 10. Using the Target meta comment
Package com.oreilly.tiger.ch06; Import Java.lang.annotation.ElementType; Import Java.lang.annotation.Target; /** * Annotation type to indicate a task still needs to be completed */ @Target ({elementtype.type, Elementtype.method, Elementtype.constructor, Elementtype.annotation_type}) Public @interface TODO { String value (); } |
The Java compiler will now apply to TODO
types, methods, constructors, and other annotation types. This helps prevent others from misusing your annotation type (or, Best of all, you will not misuse it for exhaustion).
Setting retention
The next meta-comment to use is Retention
. This meta-comment is related to how the Java compiler handles annotation types. There are several different options for the compiler:
- Leave the comment in the compiled class file and read it the first time the class is loaded.
- Leave the comment in the compiled class file, but ignore it at run time.
- Use annotations as required, but do not keep it in the compiled class file.
These three options are java.lang.annotation.RetentionPolicy
represented by enumerations, as shown in Listing 11:
Listing 11. Retentionpolicy Enumeration
Package java.lang.annotation; public enum Retentionpolicy { source,//Annotation is discarded by the compiler class,//Annotation is stored in the class file, but ignored by the VM runtime//Annotation is stored in the class file and read by the VM } |
As you can see now, the Retention
meta-annotation type uses one of the enumeration values shown in Listing 11 as the only parameter. You can use this meta-comment for your comments, as shown in Listing 12:
Listing 12. Using Retention meta comments
@Retention (Retentionpolicy.source) Public @interface Suppresswarnings { Annotation type body } |
As shown in Listing 12, this can be used in shorthand form, because Retention
there is only one member variable. If you want to set the retention to RetentionPolicy.CLASS
, then nothing needs to be done, because that's the default behavior.
Add a public document
The next meta comment is Documented
. This meta-comment is also very easy to understand, in part because it Documented
is a markup comment. You should recall that the tag comment has no member variable as mentioned in part 1th. Documented
indicates that the comment should appear in the Javadoc of the class. By default, annotations are not included in Javadoc, and you should keep this in mind if you spend a lot of time commenting on a class, detailing unfinished work, what is done correctly, or describing the behavior.
Listing 13 illustrates Documented
the use of meta-annotations:
Listing 13. Using documented meta comments
Package com.oreilly.tiger.ch06; Import java.lang.annotation.Documented; Import java.lang.annotation.Retention; Import Java.lang.annotation.RetentionPolicy; /** * Marker annotation to indicate a method or class * is still in progress. */ @Documented @Retention (Retentionpolicy.runtime) Public @interface InProgress {}
|
Documented
A practical technique is to maintain a sexual strategy. Note that the retention of annotations in Listing 13 (retention) is RUNTIME
Documented
required for the use of annotation types. Javadoc uses virtual machines to load information from its class files, rather than from source files. The only way to ensure that VMS get the information they need to generate Javadoc from these class files is to set the retention to RetentionPolicy.RUNTIME
. In this way, the annotations are persisted in the compiled class file and loaded by the virtual machine, and then Javadoc can be extracted from the HTML document that is added to the class.
Set inheritance
The last meta Inherited
-comment may be the most complex, least-used, and most confusing. That is to say, we can simply take a look at it.
The first thing to consider is that if you tag a class with a custom comment that's InProgress
being developed, it's completely fine, right? This information will also appear in Javadoc, as long as you have applied the Documented
meta-annotations correctly. Now, let's say you want to write a new class that expands the class that's still under development, isn't it? But keep in mind that the superclass is still under development. If you use a subclass, or view its documentation, there is no clue that there is nowhere else to finish. You would have liked InProgress
to see the annotations taken to the subclass-because it was inherited -but that was not the case. You must use Inherited
meta-annotations to describe the behavior you expect, as shown in Listing 14:
Listing 14. Using inherited meta comments
Package com.oreilly.tiger.ch06; Import java.lang.annotation.Documented; Import java.lang.annotation.Inherited; Import java.lang.annotation.Retention; Import Java.lang.annotation.RetentionPolicy; /** * Marker annotation to indicate a method or class * is still in progress. */ @Documented @Inherited @Retention (Retentionpolicy.runtime) Public @interface InProgress {}
|
@Inherited
once added, you will see that it InProgress
appears in the subclass of the annotation class. Of course, you do not want all annotation types to have this behavior (so the default value is not inherited). For example, TODO
annotations are not (and should not) be propagated. But it Inherited
can be very useful in the case of demonstrations here.
Conclusion
Now, you may be ready to go back to the Java world and write documents and comments for everything. This reminds me of what happens after people understand Javadoc. We are all caught up in the mire of documentation until someone realizes that it is best to use Javadoc to sort out confusing classes or methods. No matter how many articles have been made with Javadoc, no one will see those easy to understand getXXX()
and setXXX()
methods.
Annotations may also show the same trend, although not necessarily to that extent. It is a good practice to use standard annotation types frequently and even frequently. All of the Java 5 compilers support them, and their behavior is easy to understand. However, if you want to use custom annotations and meta-annotations, it is difficult to ensure that the types you create with great effort are beyond your development environment. So be cautious. Use annotations in reasonable circumstances and do not use nonsense. In any case, annotations are a great tool to provide real help in the development process.
Java Custom Annotations