Java step by step(3): Annotation

About Annotation

Java 5引入了Annotation, 这极大减轻了开发的负担,不用写很多的代码,只需要在代码中加入一些"tag"就可以了,这个很符合声明式编程(declarative programming)的思想。

当然有个问题还是要问的,虽然作为使用annotation的开发者来说,不用考虑Annotation最后究竟会被怎样执行,只要在需要使用Annotation的地方tag一下就可以,但是很显然这个只是把问题处理地点转移了而已,终归是需要有人来处理的,不然,这个Annotation就没有任何意义了。

可以想见,很多JDK提供的annotation, JVM或者编译器肯定是要负责解释处理这些anntation的。如果使用一些framework提供的annotation, 自然这些framework会提供解释执行这些annotation的代码实现,否则JVM怎么可能知道如何去解释这些tag呢。那么究竟如何去识别代码中哪些地方使用了annotation呢,很容易想到可以运用reflection来实现。

所以,annotation看起来很神秘,其实只是借助了reflection,将相关的代码实现处理逻辑封闭在一个地方,从而使得运用这些annoation的代码不需要重复实现这些功能,从而简化了工作量。

The Rules of Defining Java Annotation Types

// MyAnnotation.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
public String doSomething() default "do something";
public String date();
}

上面是一个简单的Annotation定义,Annotation的定义很特别,很像interface,不过需要在interface前面加个@符号。另外annotation中定义的method (attribute) 不能是private的,不能接受参数,不能有throws语句,返回值的类型必须是如下几种之一:

1)primitives

2)  String

3)  Class

4) Enum

5) Array of the above types

Java Annotation Types

Java 支持两种Annotation类型:

1) 简单类型:这种annotation只能用于其它code,不能用于annotation 类型。

2)Meta Annotation: 这种annotation是用于annotation type的,也就是annotation of annotation.

Out-of-the-box Simple Annotation Types in JDK

JDK提供了3个简单类型的annotations, 包括:

1) Override

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

  

可以看到Override只能用于method, 而且retention级别是SOURCE。这个Annotation的好处在于可以帮助我们快速发现问题,如果把toString写成了toString1,编译器会给出错误提示,这样就不要等到运行的时候发现出错了。  


2) Deprecated

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}

 如果一个方法或者变量被标示成Deprecated,那就意味着该方法或者变量是不应该被使用的,否则的话,编译器会报出警告信息。 


3) Suppresswarnings

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p>Compiler vendors should document the warning names they support in
* conjunction with this annotation type. They are encouraged to cooperate
* to ensure that the same names work across multiple compilers.
*/
String[] value();
}

这个Annotation是让编译器忽略某些warning信息。  


Out-of-the-box Meta Annotation Types in JDK

JDK提供了如下4种Meta Annotation Types:

1) Target

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}

这个Annotation用来标示定义的annotation类型可以用在哪些类型的元素上,包括如下几种....

-- @Target(ElementType.TYPE)

-- @Target(ElementType.FIELD) : public attributes of the class

-- @Target(ElementType.METHOD)

-- @Target(ElementType.PARAMETER)

-- @Target(ElementType.CONSTRUCTOR)

-- @Target(ElementType.LOCAL_VARIABLE)

-- @Target(ElementType.ANNOTATION_TYPE)

 

2) Retention

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
  

这个Annotation表示定义的annotation会retention的时间,有如下三种值:

-- RententionPolicy.SOURCE: retained at the source level, ignored by the compiler

-- RententionPolicy.CLASS: retained by the compiler, ignored by the VM

-- RententionPolicy.RUNTIME: retained by the VM, can be read only at run-time.


3) Documented

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

表示定义的annotation type应该被javadoc加入到生成的document中的。  


4) Inherited

/**
 * Indicates that an annotation type is automatically inherited.  If
 * an Inherited meta-annotation is present on an annotation type
 * declaration, and the user queries the annotation type on a class
 * declaration, and the class declaration has no annotation for this type,
 * then the class's superclass will automatically be queried for the
 * annotation type.  This process will be repeated until an annotation for this
 * type is found, or the top of the class hierarchy (Object)
 * is reached.  If no superclass has an annotation for this type, then
 * the query will indicate that the class in question has no such annotation.
 *
 * <p>Note that this meta-annotation type has no effect if the annotated
 * type is used to annotate anything other than a class.  Note also
 * that this meta-annotation only causes annotations to be inherited
 * from superclasses; annotations on implemented interfaces have no
 * effect.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

A Simple Example

定义一个简单的Annotation Type -- MyAnnoation

// MyAnnotation.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
public String doSomething() default "do something";
public String date();
}

  

通过Reflection来获取annotation定义的field...

// MainTest.java
public class MainTest {

@MyAnnotation(doSomething
= "Test Annotation", date = "2011-08-01")
public String annotationTest;

public void testAnnotation() {
Class aClass
= MainTest.class;
try {
Field aField
= aClass.getField("annotationTest");
MyAnnotation myAnnotation
= aField.getAnnotation(MyAnnotation.class);

annotationTest
= myAnnotation.doSomething() + " on " + myAnnotation.date();
System.out.println(
this.annotationTest);
}
catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
/**
*
@param args
*/
public static void main(String[] args) {
new MainTest().testAnnotation();
}

}

  

  

posted @ 2011-08-01 23:06  FangwenYu  阅读(466)  评论(0编辑  收藏  举报