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 { Classc = 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