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