天天看點

java注解機制_Java 注解機制

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

java注解機制_Java 注解機制
java注解機制_Java 注解機制

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

}

java注解機制_Java 注解機制
java注解機制_Java 注解機制

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中。

java注解機制_Java 注解機制
java注解機制_Java 注解機制

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作為預設值是一種常用的做法。這個限制使得處理器很難表現一個元素的存在或缺失的狀态,因為每個注解的聲明中,所有元素都存在,并且都具 有相應的值,為了繞開這個限制,我們隻能定義一些特殊的值,例如空字元串或者負數,一次表示某個元素不存在,在定義注解時,這已經成為一個習慣用法。