java.lang.annotation.Retention可以在您定义Annotation型态时,指示编 译器如何对待您的自定义 Annotation,预设上编译器会将Annotation信息留在class档案中,但不被虚拟机器读取,而仅用于编译器或工具程序运行时提供信息。
在使用Retention型态时,需要提供java.lang.annotation.RetentionPolicy的列举型态:
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, // 编译器处理完Annotation信息后就没事了
CLASS, // 编译器将Annotation储存于class档中,预设
RUNTIME // 编译器将Annotation储存于class檔中,可由VM读入
}
RetentionPolicy为SOURCE的例子是SuppressWarnings,这个信息的作用仅在告知编译器抑制警讯,所以不必将这个信息储 存于class档案。
RetentionPolicy为RUNTIME的时机,可像是您使用Java设计一个程序代码分析工具,您要VM读出Annotation信息,以在分析 程序中使用,搭配Reflection机制,就可以达到这个目的。
在J2SE 5.0中新增了java.lang.reflect.AnnotatedElement这个接口,当中定义有四个方法:
public Annotation getAnnotation(Class annotationType); public Annotation[] getAnnotations(); public Annotation[] getDeclaredAnnotations(); public boolean isAnnotationPresent(Class annotationType);
Class、Constructor、Field、Method、Package等类别,都实作了 AnnotatedElement这个接口,所以您可以从这些类别的实例上,分别取得标示于其上的Annotation与其信息,如果 RetentionPolicy为RUNTIME的话。
举个例子来说,假设您设计了以下的Debug Annotation:
package onlyfun.caterpillar;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Debug {
String value();
String name();
}
由于RetentionPolicy为RUNTIME,编译器在处理Debug Annotation时,会将之编译至class档中,并可以VM读出Annotation信息,接着我们将Debug用于程序中:
package onlyfun.caterpillar;
public class SomeObject {
@Debug(
value = "unit",
name = "debug1"
)
public void doSomething() {?
// ....
}
}
可以设计一个工具程序来读取Annotation信息:
package onlyfun.caterpillar;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class DebugTool {
public static void main(String[] args)
throws NoSuchMethodException {
Class c = SomeObject.class;
Method method = c.getMethod("doSomething");
if(method.isAnnotationPresent(Debug.class)) {
System.out.println("@Debug is found.");
Debug debug = method.getAnnotation(Debug.class);
System.out.println("\tvalue = " + debug.value());
System.out.println("\tname = " + debug.name());
}
else {
System.out.println("@Debug is not found.");
}
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations) {
System.out.println(
annotation.annotationType().getName());
}
}
}
程序的执行结果如下:
@Debug is found. value = unit name = debug1 onlyfun.caterpillar.Debug