一、注解中的資訊已經在Class中了,我們應該如何讀取出來

1 java.lang.reflect.AnnotatedElement接口:2
3 publicAnnotation[] getAnnotation(Class annotationType);4
5 publicAnnotation[] getDeclaredAnnotations();6
7 public Boolean isAnnotationPresent(Class annotationType);
View Code
Class 、Constructor、Field、Method、Package等類别,都實作了AnnotatedElement接口,既然Class 、Constructor、Field、Method、Package等類别,都實作了AnnotatedElement接口,顯然它們都可以去調用AnnotatedElement裡面的方法,以上各方法是定義在這個接口中的,定義Annotation時必須設定RententionPolicy為RUNTIME,也就是可以在VM中讀取Annotation資訊
二、通過反射的方式讀取作用在類、方法上面所修飾的注解資訊。
1、public boolean isAnnotationPresent(Class extends Annotation> annotationClass)
這句代碼表示:annotationClass指定的注解,如果存在于方法的上面,就傳回一個true,這個方法主要是用來判斷某個方法上面是否存在注解。
2、public T getAnnotation(Class annotationClass)
會傳回一個Annotation這樣一個對象,參數裡邊兒是一個具體的Annotation Class對象,如果這樣一個Annotation存在的話,才會傳回這個Annotation。否則傳回一個空值
3、Class extends Annotation> annotationType()
傳回注解所對應的Class對象。
三、限定annotation使用對象
@Target
使用java.lang.annotation.Target可以定義其使用之時機,就是限定可以在什麼地方可以使用注解:如方法、類、成員屬性、變量,在定義時要指定java.lang.annotation.ElementType的枚舉值之一,以此來表示這個注解可以修飾哪些目标。
package java.lang.annotation
public Enum ElementType{
TYPE,//适用class,interface,enum
FIELD,//适用field
METHOD,//适用method
PARAMETER,//适用method之上的parater
CONSTTRUCTOR,//适用constructor
LOCAL_VARIABLE,//适用局部變量
ANNOTATION_TYPE,//适用annotation型态
PACKAGE//适用package
}

1 packagecom.javase.annotation;2 importjava.lang.annotation.ElementType;3 importjava.lang.annotation.Target;4
9 @Target(ElementType.METHOD)10 public @interfaceMyTarget {11 String value();12 }13
14 packagecom.javase.annotation;15
16 public classMyTargetTest {17 @MyTarget(value="zhangsan")18 public voiddoSomething(){19 System.out.println("hello world");20 }21 }
View Code
四、要求為API檔案@Documented
在制作JavaDoc檔案的同時,如果想要将Annotation的内容也加入到API檔案中,需要使用java.lang.annotation.Documented,則在在生成java doc的時候,将注解資訊也生成到java doc中。

1 packagecom.javase.annotation;2 importjava.lang.annotation.Documented;3
4 @Documented5 public @interfaceDocumentedAnnotation {6 String hello();7 }8 packagecom.javase.annotation;9
10 public classDocumentedTest {11 @DocumentedAnnotation(hello="welcome")12 public voidmethod(){13 System.out.println("helloworld");14 }15 }
View Code
五、@Inherited
在定義Annotation時加上java.lang.annotation.Inherited形态的Annotation,Inherited表示一個注解資訊是否可以被自動繼承下來,如果在注解中加上Inherited注解,就會由父類中被子類繼承下來。
六:總結
1、要知道注解的本源是什麼,如何去定義注解。
2、如何使用反射的方式去解析注解的資訊,并且去解析注解下面所修飾的類、方法。根據注解是否存在注解的值到底是什麼,來去調用對應的方法,或者處理對應的類。這個是很重要的,将RetentionPolicy設定為RUNTIME就可以得到。
3、元注解的作用就是負責注解其他注解。Java5.0定義了4個标準的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。Java5.0定義的元注解:
[email protected],
[email protected],
[email protected],
[email protected]
這些類型和它們所支援的類在java.lang.annotation包中可以找到。
4、@Target:
@Target說明了Annotation所修飾的對象範圍:Annotation可被用于 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循 環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目标。
作用:用于描述注解的使用範圍(即:被描述的注解可以用在什麼地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述構造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部變量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述參數
7.TYPE:用于描述類、接口(包括注解類型) 或enum聲明
5、@Retention:
@Retention定義了該Annotation被保留的時間長短:某些Annotation僅出現在源代碼中,而被編譯器丢棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛拟機忽略,而另一些在class 被裝載時将被讀取(請注意并不影響class的執行,因為Annotation與class在使用上是被分離的)。使用這個meta- Annotation可以對 Annotation的“生命周期”限制。
作用:表示需要在什麼級别儲存該注釋資訊,用于描述注解的生命周期(即:被描述的注解在什麼範圍内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源檔案中有效(即源檔案保留)
2.CLASS:在class檔案中有效(即class保留)
3.RUNTIME:在運作時有效(即運作時保留)
Retention meta-annotation類型有唯一的value作為成員,它的取值來自java.lang.annotation.RetentionPolicy的枚舉類型值。
6、@Documented:
@Documented用于描述其它類型的annotation應該被作為被标注的程式成員的公共API,是以可以被例如javadoc此類的工具文檔化。Documented是一個标記注解,沒有成員。
7、@Inherited:
@Inherited 元注解是一個标記注解,@Inherited闡述了某個被标注的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用于一個class,則這個annotation将被用于該class的子類。注意:@Inherited annotation類型是被标注過的class的子類所繼承。類并不從它所實作的接口繼承annotation,方法并不從它所重載的方法繼承annotation。當@Inherited annotation類型标注的annotation的Retention是RetentionPolicy.RUNTIME,則反射API增強了這種繼 承性。如果我們使用java.lang.reflect去查詢一個@Inherited annotation類型的annotation時,反射代碼檢查将展開工作:檢查class和其父類,直到發現指定的annotation類型被發現, 或者到達類繼承結構的頂層。
8、自定義注解:
使用@interface自定義注解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程式自動完成 其他細節。在定義注解時,不能繼承其他的注解或接口。@interface用來聲明一個注解,其中的每一個方法實際上是聲明了一個配置參數。方法的名稱就 是參數的名稱,傳回值類型就是參數的類型(傳回值類型隻能是基本類型、Class、String、enum)。可以通過default來聲明參數的預設 值。
定義注解格式:
public @interface 注解名 {定義體}
注解參數的可支援資料類型:
1.所有基本資料類型(int,float,boolean,byte,double,char,long,short)
2.String類型
3.Class類型
4.enum類型
5.Annotation類型
6.以上所有類型的數組
Annotation類型裡面的參數該怎麼設定:
第一,隻能用public或預設(default)這兩個通路權修飾.例如,String value();這裡把方法設為defaul預設類型;
第二,參數成員隻能用基本類型byte,short,char,int,long,float,double,boolean八種基本資料類型和
String,Enum,Class,annotations等資料類型,以及這一些類型的數組.例如,String
value();這裡的參數成員就為String;
第三,如果隻有一個參數成員,最好把參數名稱設為"value",後加小括号.例:下面的例子FruitName注解就隻有一個參數成員。
9、注解元素的預設值:
注解元素必須有确定的值,要麼在定義注 解的預設值中指定,要麼在使用注解時指定,非基本類型的注解元素的值不可為null。是以, 使用空字元串或0作為預設值是一種常用的做法。這個限制使得處理器很難表現一個元素的存在或缺失的狀态,因為每個注解的聲明中,所有元素都存在,并且都具 有相應的值,為了繞開這個限制,我們隻能定義一些特殊的值,例如空字元串或者負數,一次表示某個元素不存在,在定義注解時,這已經成為一個習慣用法。