Java Annotation使用大全
三、Annotation工作原理:
Annotation与反射
在java5.0 中Java.lang.reflect提供的反射API被扩充了读取运行时annotation的能力。让我们回顾一下前面所讲的:一个 annotation类型被定义为runtime retention后,它才是在运行时可见,当class文件被装载时被保存在class文件中的annotation才会被虚拟机读取。那么 reflect是如何帮助我们访问class中的annotation呢?
下文将在java.lang.reflect用于 annotation的新特性,其中java.lang.reflect.AnnotatedElement是重要的接口,它代表了提供查询 annotation能力的程序成员。这个接口被java.lang.Package、java.lang.Class实现,并间接地被Method类、 Constructor类、java.lang.reflect的Field类实现。而annotation中的方法参数可以通过Method类、 Constructor类的getParameterAnnotations()方法获得。
下面的代码使用了AnnotatedElement类的isAnnotationPresent()方法判断某个方法是否具有@Unstable annotation,从而断言此方法是否稳定:
清单8:
import java.lang.reflect.*;
Class c = WhizzBangClass.class;
Method m = c.getMethod("whizzy", int.class, int.class);
boolean unstable = m.isAnnotationPresent(Unstable.class);
isAnnotationPresent ()方法对于检查marker annotation是十分有用的,因为marker annotation没有成员变量,所以我们只要知道class的方法是否使用了annotation修饰就可以了。而当处理具有成员的 annotation时,我们通过使用getAnnotation()方法来获得annotation的成员信息(成员名称、成员值)。这里我们看到了一套优美的java annotation系统:如果annotation存在,那么实现了相应的annotation类型接口的对象将被getAnnotation()方法返回,接着调用定义在annotation类型中的成员方法可以方便地获得任何成员值。
回想一下,前面介绍的@Reviews annotation,如果这个annotation类型被声明为runtime retention的话,我们通过下面的代码来访问@Reviews annotation的成员值:
清单9:
AnnotatedElement target = WhizzBangClass.class; //获得被查询的AnnotatedElement
// 查询AnnotatedElement的@Reviews annotation信息
Reviews annotation = target.getAnnotation(Reviews.class);
// 因为@Reviews annotation类型的成员为@Review annotation类型的数组,
// 所以下面声明了Review[] reviews保存@Reviews annotation类型的value成员值。
Review[] reviews = annotation.value();
// 查询每个@Review annotation的成员信息
for(Review r : reviews) {
Review.Grade grade = r.grade();
String reviewer = r.reviewer();
String comment = r.comment();
System.out.printf("%s assigned a grade of %s and comment '%s'%n",
reviewer, grade, comment);
}