大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 告知编译器如何处理 annotaion - Retention

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:

  • Debug.java
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用于程序中:
  • SomeObject.java
package onlyfun.caterpillar;

public class SomeObject {
@Debug(
value = "unit",
name = "debug1"
)
public void doSomething() {
// ....
}
}


可以设计一个工具程序来读取Annotation信息:

  • DebugTool.java
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<SomeObject> 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