Take full advantage of Java metadata, part 2nd: custom Annotations __java

Source: Internet
Author: User
Tags deprecated

Take full advantage of Java metadata, part 2nd: Customizing annotations
Author: Jason Hunter

Learn how to write your own annotation types and use built-in annotations to control their behavior.

In my previous article in this series, I introduced the new metadata tools for Java and the built-in annotation types @Override, @Deprecated, and @SuppressWarnings. In this article, I'll explain how to write your own annotation types and control the behavior of annotations using built-in annotations in the Java.lang.annotation package.

When I think of a custom annotation, there are several thoughts in my mind. Suppose you write a @ThreadSafe annotation to declare a thread-safe design of a class or method to any caller, or write a @NotThreadSafe to use as a warning. Suppose you write a @Copyright ("Jason Hunter") annotation to specify the copyright for the class file in bytecode, and you can write a corresponding @License (license.apache20) annotation to specify the terms of the shared code. Unlike copyright and license statements contained in comments, these annotations can be retained after compilation and can be documented programmatically. Maybe you have your own ideas, but you have to do a lot of experiments anyway. This article will help to start these experiments.

@Unfinished annotation Type

In the example in this article, we'll assume and create a @Unfinished annotation type. The idea for the example comes from a common scenario where you write the outline of a block of code and some classes or methods are not yet complete-a basic structure that you can add to the code later. You may like me to mark these areas with some "XXX" or "TODO" comments (or other easily searchable annotations). Using Java metadata and custom annotation types, you can use annotations to mark these code structures as @Unfinished instead.

This method provides several meaningful possibilities. For example, you can make any unit test that calls an incomplete code produce a special "unfinished" result that distinguishes it from a general failure at run time. You can also export a warning at compile time and mark it as "effectively unfinished" whenever the thoroughly completed code has dependencies with the unfinished code. In addition, because annotations can usually take any format, you can write an annotation type to accept a description string, an optional owner list, and a priority (with an assumed default value).

Use special @interface syntax to write annotations:

Public @interface Unfinished {}  //Unfinished.java
@interface are very much like annotations but not exactly the same. It can be treated as a pseudo annotation, meaning that it simply marks the class as an annotation. As described in the comments above, you place annotations in a regular. Java source file. Annotations are compiled down to the regular. class file.

The annotation is missing a large number of attributes, so it is now marked as unfinished (incomplete) by self referencing:

@Unfinished public
@interface unfinished {}
Annotation parameters

To provide its description, owner, and priority for @Unfinished annotation type, you will need to add parameters to the annotation declaration. Annotation parameters follow certain strict rules: parameter types can only be primitive, String, Class, enum, annotation, or an array of any type. The parameter value must never be empty. Each parameter can declare a default value. You can set an argument named "Value" with the abbreviation style. Parameters are written as simple methods (no parameters, no throw clauses, etc.). The following is an improved version of @Unfinished, which is closer to the completion status:

@Unfinished ("Just articleware") public
@interface unfinished {public
enum Priority {Low, MEDIUM, high}

Str ing value ();
String[] Owners () default "";
Priority Priority () default priority.medium;
}
There are several important points to note about this short example. First, we have added parameters using a surface-like method declaration syntax: value (), owners (), and priority (). As you will see in my next article, these methods are used as getter that can be invoked at run time.

The name of the "value" parameter is special, and it is used only when the property passes a parameter. This can be seen from the "Just articleware" annotation. We must add this description because the "value" parameter does not declare a default value, so a compilation error is generated using annotations that are not described:

Unfinished.java:4:annotation unfinished is missing value
@Unfinished
 ^
1 Error
We can actually allow no parameters by providing a default value for the value () parameter (just as we provide the default value for the owners () parameter). Note how the owners () parameter uses a simple string as the default value, and the parameter is of type string. The ability to do so is fully benefited from the VarArgs (another J2SE 5.0 feature). (For more information about VarArgs and the new enumeration tool for defining Priority types, see my previous article in cuisine.) )

You may find it strange to use "default" in a declaration, but the "default" keyword is not a new keyword that Java has previously used in a switch statement. To determine whether a language is mature is to see whether each keyword has multiple uses.

The following is an example that demonstrates @Unfinished parameter attributes:

@Unfinished (
value= "class scope",
priority=unfinished.priority.low
) public
class Unfinisheddemo {

@Unfinished ("constructor scope") public
Unfinisheddemo () {}

@Unfinished (owner= "Jason", value=) Scope ") Public
void foo () {}
}}
The first use case of this parameter marks the entire class as a unfinished with a low priority and no owner specified. The second use case marks the constructor as unfinished and provides only the required description, without providing the specified owner or priority. The last use case marks the Foo () method as unfinished and provides the owner and description, while moving the description to the second parameter rather than the first argument to explain the order of named arguments is not important.

How the package level is annotated. Because there are no specific places to place these annotations, they are placed in a specially-specified Package-info.java file. As shown below:

Package-info.java
@Unfinished ("Package scope")
package com.servlets;
You need to include a package statement to indicate which package the annotation is placed in. You cannot assume that the location on the disk is reliable.

To compile the Package-info.java example above, @Unfinished annotations cannot be in the default package. Before J2SE 1.4, you can import the classes in the default package using the syntax shown below:

Import unfinished;
This syntax has been disabled for use. Therefore, accessing the default package class from the encapsulated class requires that the default package class be moved to its own package. So, from now on, move the @Unfinished into the Com.servlets package:
Package com.servlets;

@Unfinished ("Just articleware") public
@interface unfinished {...
Now we want @Unfinished to follow several other rules: it should not be attached to a field, parameter, or local variable (it doesn't work in those locations). It should appear in Javadoc. And it should persist at run time. As you have guessed, we have specified such a rule as an annotation.

Annotations for annotations

J2SE 5.0 provides four annotations in the Java.lang.annotation package that are used only when writing annotations: @Documented-whether to place annotations in Javadoc @Retention-when annotations are needed @Target-batch The target @Inherited of the note-whether or not the subclass gets the annotation The four annotations are described in turn.

@Documented

By default, annotations of a class or method do not appear in the Javadoc of that class or method. @Documented annotation changes this situation. It is a simple markup annotation and does not accept parameters. With @Unfinished, we want users to know what classes and methods work is not finished, so we will use this meta annotation to mark @Unfinished:

Package com.servlets;
Import java.lang.annotation.*;

@Unfinished ("Just articleware")
@Documented public
@interface unfinished {...
Note the new import line and multiple annotations at the same level. You can place multiple annotations on an element, but you cannot place two annotations of the same type. After making this change, you will see the following in the Javadoc of the previous Unfinisheddemo example:

@Retention

How long you need to keep the annotations. Three options are listed in the Retentionpolicy enumeration:

Options Notes Sample
Retentionpolicy.source Discarded during the compilation process. When the compilation is complete, these annotations will not work, so they will not be written to byte code. @Override, @SuppressWarnings
Retentionpolicy.class discarded during class loading. is useful when performing post-processing at the bytecode level. Some people are surprised that this is the default value. -
Retentionpolicy.runtime Not discarded so that the runtime can be used to reflect. @Deprecated

@Retention annotation allows you to specify the desired retentionpolicy for the custom annotation type; it accepts a retentionpolicy type of "value" parameter. To make the @Unfinished sample retentionpolicy.runtime more meaningful, you can make the following changes.
Package com.servlets;
Import java.lang.annotation.*;

@Unfinished ("Just articleware")
@Documented
@Retention (retentionpolicy.runtime) public
@interface Unfinished {.....
In my next article, I'll explain how to read annotations at run time.

@Target

Now, where do you want to put the annotation? Eight options are listed in the ElementType enumeration: Elementtype.type (class, Interface, enum) Elementtype.field (instance variable) Elementtype.method elementtype.parameter elementtype.constructor elementtype.local_variable ElementType.ANNOTATION _type (on another annotation) Elementtype.package (remember Package-info.java) when you know the list of places you can use, use @Target annotation (accept Array of ElementType values) to specify the location. It's just a list of integrity, which means you can't exclude any location, but you must list the seven allowed locations. The default setting when @Target does not exist is to allow any location. @Unfinished example works in five locations, so we can specify it as follows:

Package com.servlets;
Import java.lang.annotation.*;

@Unfinished ("Just articleware")
@Documented
@Retention (retentionpolicy.runtime)
@Target ({ Elementtype.type,elementtype.method,
Elementtype.constructor,elementtype.annotation_type,
Elementtype.package}) Public
@interface unfinished {...
@Inherited

Finally, @Inherited control whether annotations affect subclasses. For example, @Unfinished whether the superclass indicates an incomplete subclass. Perhaps instructions, so the following is the final format of the @Unfinished:

Package com.servlets;
Import java.lang.annotation.*;

@Documented
@Retention (retentionpolicy.runtime)
@Target ({elementtype.type,elementtype.method,
Elementtype.constructor,elementtype.annotation_type,
elementtype.package})
@Inherited public
@ Interface Unfinished {public
enum Priority {Low, MEDIUM, high}

String value ();
String[] Owners () default "";
Priority Priority () default priority.medium;
}
Subsequent articles

In the next article in this series, I'll show you how to enhance the reflection capabilities of Java to help you discover annotations at run time, and explain how to use annotations at build time with the annotation processing tool "apt".   

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.