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();
}
}