Notes on Annotations


Notes on Annotations

Annotations
Annotations are tags that we insert into we source code so that some tool can process them. The tools can operate on the source level, or they can process class files into which the compiler has placed annotations.
Annotations provide a formalized way to add information to the code so that we can easily use that data at some later point.
Annotations are partly motivated by a general trend toward combining metadata with source-code files, instead of keeping it in external documents.

Using annotations, we can keep this metadata in the Java source code, and have the advantage of cleaner looking code, compile-time type checking and the annotation API to help build processing tools for our annotations.
To benefit from annotations, we need to select a processing tool. We insert annotations into our code that our processing tool understands, and then apply the processing tool.

Annotations can be processed at runtime, at the source code level, or at the bytecode level.
Defining annotations
Defining annotations is very easy; Annotation type declarations are similar to normal interface declarations. An at-sign (@) precedes the interface keyword. Then we declare meta-annotations on the annotation interface such as @Target to define where we can apply this annotation (a method or a field, for example), @Retention to define whether the annotations are available in the source code (SOURCE), in the class files (CLASS), or at run time (RUNTIME).

Then we declare elements in this annotation interface, elements look like interface methods, except that we can declare default values.
Methods can have default values. Method declarations must not have any parameters or a throws clause. Return types are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types.
Annotations can be read from source files, class files, or reflectively at run time.

The annotations don't do anything by themselves, without tools to read them; annotations are hardly more useful than comments.
We need write annotation processors to read and process annotations. Java SE5 provides extensions to the reflection API to read annotations defined in java class.
Annotation Syntax

An annotation without any elements is called a marker annotation.
An annotation is defined by an annotation interface, Each element declaration has the form: type elementName() default value;
Each annotation has the format
@AnnotationName(elementName1=value1, elementName2=value2, . . .)
The order of the elements does not matter.
Two special shortcuts can simplify annotations:
If no elements are specified, then we don't need to use parentheses: @BugReport
The other shortcut is the single value annotation. If an element has the special name value, and no other element is specified, then we can omit the element name and the = symbol.
@ActionListenerFor("yellowButton") is same as @ActionListenerFor(value="yellowButton")
Limitations when implement annotations
The methods of an annotation interface can have no parameters and no throws clauses, and they cannot be generic.
The type of an annotation element is one of the following: A primitive type, String, Class (with an optional type parameter such as Class), an enum type, an annotation type, 1-dimensional arrays of the preceding types (an array of arrays is not a legal element type)
The compiler will report an error if you try to use any other types. Note that you are not allowed to use any of the wrapper classes, but because of autoboxing this isn’t really a limitation. You can also have elements that are themselves annotations.
//When a Target meta-annotation is not present on an
//annotation type declaration, the declared type may be used on any
//program element.
//If no Retention annotation is present on an annotation type declaration,
//the retention policy defaults to RetentionPolicy.CLASS.
public @interface BugReport {
    enum Status {
       UNCONFIRMED, CONFIRMED, FIXED, NOTABUG
    };
    boolean showStopper() default false;
    String assignedTo() default "[none]";
    Class testCase() default Void.class; // we can use class
    Status status() default Status.UNCONFIRMED; // we can use enum
    Reference ref() default @Reference(); // an annotation type
    String[] reportedBy();
    // Compile error: Invalid type Object for the annotation attribute
    // BugReport.object; only primitive type, String,
    // Class, annotation, enumeration are permitted or 1-dimensional arrays thereof
    Object object();
}
Annotation values must be compile-time constants, so you can't call method to set annotation values.
// Compile error: The value for annotation attribute ActionListenerFor.source must be a constant expression
@ActionListenerFor(source = "blueButton" + anyMethod())
An annotation element can never be set to null. Not even a default of null is permissible.
Annotations don’t support inheritance, you cannot use the “extends” keyword with @interfaces.
If annotations (retention class) are evaluated by the compiler, all element values must be compile-time constants.
An item can have multiple annotations, provided they belong to different types. We cannot use the same annotation type more than once when annotating a particular item.
If this is a problem, we can design an annotation that has a value of an array of simpler annotations.
Default value constraints
The compiler is quite picky about default element values. No element can have an unspecified value. This means that elements must either have default values or values provided by the class that uses the annotation.
There is another restriction, which is that none of the non-primitive type elements are allowed to take null as a value, either when declared in the source code or when defined as a default value in the annotation interface. You need define special value as default value.
It is legal to apply an annotation to itself. For example, the @Documented annotation is itself annotated as @Documented.
Annotations for local variables can only be processed at the source level. Class files do not describe local variables. Therefore, all local variable annotations are discarded when a class is compiled. Similarly, annotations for packages are not retained beyond the source level.
Implementation detail
All annotation interfaces implicitly extend the interface java.lang.annotation.Annotation. That interface is a regular interface, not an annotation interface.
Standard Annotations
Meta-Annotations
@Target
The @Target meta-annotation restricts the items to which the annotation applies.
@Target(ElementType.ANNOTATION_TYPE)
public enum ElementType
{TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,,ANNOTATION_TYPE,PACKAGE}
An annotation without an @Target restriction can be applied to any program element. The compiler checks that we apply an annotation only to a permitted item.
@Retention
The @Retention meta-annotation specifies how long an annotation is retained. We specify at most one of the values.
@Retention(RetentionPolicy.RUNTIME)
SOURCE Annotations are not included in class files.
CLASS   Annotations are included in class files, but the virtual machine need not load them.
RUNTIME Annotations are included in class files and loaded by the virtual machine. They are available through the reflection API.
public enum RetentionPolicy {
   * Annotations are to be discarded by the compiler.
  SOURCE,
   * Annotations are to be recorded in the class file by the compiler
   * but need not be retained by the VM at run time. This is the default behavior.
  CLASS,
   * Annotations are to be recorded in the class file by the compiler and
   * retained by the VM at run time, so they may be read reflectively.
  RUNTIME
}
If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS.
The @Documented meta-annotation gives a hint to documentation tools such as Javadoc.
@Inherited
The @Inherited meta-annotation applies only to annotations for classes. When a class has an inherited annotation, then all of its subclasses automatically have the same annotation.
Annotations for Compilation
@Deprecated
The @SuppressWarnings annotation tells the compiler to suppress warnings of a particular type: @SuppressWarnings("unchecked")
The @Override annotation applies only to methods. The compiler checks that a method with this annotation really overrides a method from the superclass.
The @Generated annotation is intended for use by code generator tools. Any generated source code can be annotated to differentiate it from programmer-provided code.
Annotations for Managing Resources
@PostConstruct, @PreDestroy, @Resource
Practical usage
Source-Level Annotation Processing
One use for annotation is the automatic generation of "side files" that contain additional information about programs
Bytecode Engineering
We can process class files using Bytecode Engineering Library (BCEL).
Generating external files
How Junit process annotation.

Resources:

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)