Annotation簡介:
          Annotation提供一種機制,將程序中元素(如類、方法、屬性等)和元數據聯系起來。這樣編譯器可以將元數據保存的class文件中。代碼分析工具就可以使用這些元數據執行的額外任務。注釋采用“at”標記形式 ( @ ),后面是注釋名稱。

自定義 annotationDebug.java
package annotation.test;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

    
/*
     * annotation類型是一種接口,能夠通過java反射API的方式提供對其信息的訪問
     
*/


    
/*
     * Documented 產生Java Doc文件,這次可以看到文件中包括了@Debug的信息
     
*/

@Documented
    
/*
     * 限定 annotation 使用對象 - Target 
     * 在定義annotation時,使用java.lang.annotation.Target可以定義annotation使用的時機。
     * public enum ElementType {
     *   TYPE, // 適用 class, interface, enum
     *   FIELD, // 適用 field
     *   METHOD, // 適用 method
     *   PARAMETER, // 適用 method 上之 parameter
     *   CONSTRUCTOR, // 適用 constructor
     *   LOCAL_VARIABLE, // 適用區域變量
     *   ANNOTATION_TYPE, // 適用 annotation 型態
     *   PACKAGE // 適用 package
     *   } 
     
*/

@Target(
{ElementType.CONSTRUCTOR, ElementType.METHOD})//指定目標
    /*
     * Retention 在你自定義的形態中,指定編譯器如何處理自定義的annotation
     * 告知編譯器如何處理 annotaion - Retention 
     * RetentionPolicy
     *         SOURCE        編譯器處理完Annotation信息后就沒事了
     *         CLASS        編譯器將Annotation儲存于class檔中,預設
     *         RUNTIME        編譯器將Annotation儲存于class檔中,可由VM讀入
     *                     使用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的話。

     
*/

     
@Retention(RetentionPolicy.RUNTIME)
//設置保持性
    /*
     * @Inherited 子類是否繼承父類的 annotation 
     
*/

@Inherited
public @interface Debug {
    
//定義了value()方法,編譯器在編譯時會自動幫您產生一個value的變量成員,接著在使用Debug Annotation時要指定值
    
//注釋類型的數據成員被設置成使用有限信息進行工作
    
//定義數據成員不需要分別定義訪問和修改的方法,只需定義一個方法,以數據成員的名稱命名它,數據類型應該是該方法返回值的類型.
    String value()default "windfree";//默認值的類型必需與成員變量的申明類型一置
    String name();
}



在程序中使用自定義的annotation
   TestDebug.java
package annotation.test;

public class TestDebug {
    @Debug(
               name 
= "zgliu"
            )
     
public void doSomething() {        
        }

}


使用java中反射API讀取class中的元數據的信息
      DebugTool.java:
package annotation.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class DebugTool {
    
public static void main(String []args)throws NoSuchMethodException {
        Class
<TestDebug> c=TestDebug.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());
        }

    }

}

Java標準Annotation
@Deprecated 相當于Javadoc的@deprecated,被@Deprecated標注的對象class, method等被注明為不推薦使用。主要用于javac等編譯工具。
@Override 注明對象method重載了父類的方法。javac等編譯工具編譯時會根據此Annotation判斷重載方法是否正確。
@SuppressWarnings 告訴javac等編譯器忽略所指定的特定的警告信息。
@Target 被定義的annotation可以附加在那些對象上。
@Retention annotation的作用期間。

定義一個annotation
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {①定義一個注釋
int init();
}


import java.lang.annotation.Annotation;
public class TestAnnotation {
  @MyAnnotation(init 
= 2)②使用注釋
  
public void print(){
     System.out.println(TestAnnotation.
class.getName());
  }

  
public static void main(String[] args) throws Exception{
     TestAnnotation ta 
= new TestAnnotation();
     Annotation[] annotations 
= ta.getClass().getMethod("print").getAnnotations();③
     
for (Annotation annotation : annotations)  {              
         System.out.println(
"MyAnnotation.init : " + 
       ((MyAnnotation)annotation).init());④打印出init的值
        }
 
  }

}



我們定義了一個名為MyAnnotation的注釋而這個注釋中只有一個類型為int名為init的屬性,我們在②處使用了我們剛剛定義的注釋并且為init賦值為2,在③處我們通過反射機制獲得print方法上定義的所有注釋然后通過迭代將其值init打印至控制臺。

最終在控制臺輸出以下信息:
MyAnnotation.init : 2