天天看點

Java中的@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 = " + ()); 

  } 

  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