Java中Annotation(註釋)系列學習筆記(3)

【轉】Java中Annotation(註釋)系列學習筆記(3)

三.JDK的元Annotation
  JDK除了java.lang下提供了3個基本Annotation之外,還在java.lang.annotation包下提供了四個Meta Annotation(元Annotation),這四個都是用於修飾其它Annotation定義

(1)使用@Retention
  @Retention只能用於修飾一個Annotation定義,用於該Annotation可以保留多長時間,@Retention包含一個RetentionPolicy類型的value成員變量,所以使用@Retention時必須爲該value成員變量指定值.
value成員變量的值只能是如下三個

RetentionPolicy.CLASS:編譯器將把註釋記錄在class文件中。當運行Java程序時,JVM不再保留註釋。這是默認值。
RentionPolicy.RUNTIME:編譯器將把註釋記錄在class文件中。當運行java程序時,JVM也會保留註釋,程序也可以通過反射獲取該註釋。
RentionPolicy.SOURCE:編譯器直接丟棄這種策略的註釋。

  在前面的程序中,因爲我們要通過反射獲取註釋信息,所以我們指定value屬性值爲RetentionPolicy.RUNTIME. 使用@Retention元數據Annotation可採用如下代碼爲value指定值.


//定義下面的Testable Annotation的保留到過行時
@Retention(value=RetentionPolicy.RUNTIME)
public @interface Testable{}

 

也可以採用如下代碼來爲value指定值
@Retention(RetentionPolicy.SOURCE)
public @interface Testable{}

  上面代碼使用@Retention元數據Annotation時,並未直接通過value=RetentionPolicy.SOURCE的方式來爲成員變量指定值,這是因爲如果Annotation的成員變量名爲value時,程序中可以直接在Annotation後的括號裏指定該成員變量的值,無須用name=value的形式.

說明
  如果我們定義的Annotation類型裏只有一個value成員變量,使用該Annotation時可以直接在Annotation後的括號裏指定value成員變量的值,無須使用name=value的形式。

 

(2)使用@Target
  @Target也是用於修飾一個Annotation定義,它用於指定被修飾的Annotation能用於修飾哪些程序元素。@Target Annotation也包含一個名爲value的成員變量。該成員變量的值只能是如下幾個

ElementType.ANNOTATION_TYPE: 指定該策略的Annotation只能修飾Annotation
ElementType.CONSTRUCTOR:指定該策略的Annotation能修飾構造器
ElementType.FIELD:指定該策略的Annotation只能修飾成員變量
ElementType.LOCAL_VARIABLE:指定該策略的Annotation只能修飾局部變量
ElementType.METHOD 指定該策略的Annotation只能修飾方法定義
ElementType.PACKAGE 指定該策略的Annotaion只能修飾包定義
ElementType.PARAMETER 指定該策略的Annotation可以修飾參數
ElementType.TYPE 指定該策略的Annotaion可以修飾類,接口(包括註釋類型)或枚舉定義

  與使用@Retention類似的是,使用@Target也可以直接在括號裏指定value值,可以無須使用name=value的形式。如

下代碼指定@ActionListenerFor Annotation只能修飾成員變量
@Target(ElementType.FIELD)
public @interface ActionListenerFor{}

 

如下代碼指定@Testable Annotation只能修飾方法
@Target(ElementType.METHOD)
public @interface Testable{}

 

(3)使用@Documented
  @Documented用於指定該元Annotation修飾的Annotation類將被javadoc工具提取成文檔,如果定義Annotatin類時使用了@Documented修飾,則所有使用該Annotation修飾的程序元素API文檔中將會包含該Annotation說明

  下面程序定義了一個Testable Annotation程序使用@Documented來修飾@Testable Annotation定義,所以該Annotation將被 javadoc工具提取
@Retention(RetentionPolicy.RUNTIME)   
@Target(ElementType.METHOD)
//定義Testable Annotation將被javadoc工具提取
@Documented
public @interface Testable
{
}


  上面程序中的@Documented代碼決定了所有使用@Testable Annotation的地方都會被javadoc工具提取到api文檔中

  下面程序中定義了一個 MyTest類,該類中的infor方法使用Testable Annotation修飾
程序清單
public class MyTest
{
 //使用@Testable修飾info方法
 @Testable
 public void info()
 {
  System.out.println("info方法...");
 }
}


使用javadoc工具爲Testable.java ,MyTest文件生成api文檔後如下面所示



如果,我們去掉不用@Documented修飾Testable的話,則不會被javadoc提取


(4)使用@Inherited
  @Inherited元Annotation指定被它修飾的Annotation將具有繼承性。如果某個類使用了Annotaion(使用Annotation時使用了@Inherited修飾)修飾,則其子類將自動具有A註釋。

 

下面使用@Inherited元數據註釋定義了一個Inherited Annotation,該Annotation將具有繼承性

程序清單
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
// @Inherited
public @interface Inheritable
{
}

  上面程序中表明瞭@Inheritable Annotation具有繼承性,如果某個類使用了該Annotation 修飾,則該類的子類將自動具有@Inheritable Annotation

  下面程序定義了一個Base基類,該基類使用了@Inherited修飾,則Base類的子類將自動具有@Inherited Annotation

程序清單
//使用@Inheritable修飾的Base類
@Inheritable
class Base
{
}
//TestInheritable類只是繼承了Base類,
//並未直接使用@Inheritable Annotiation修飾
public class TestInheritable extends Base
{
 public static void main(String[] args)
 {
  //打印TestInheritable類是否具有Inheritable Annotation
  System.out.println(TestInheritable.class.isAnnotationPresent(Inheritable.class));
 }
}

 

運行效果圖如下




總結
  1.
上面程序中的Base類使用了@Inheritable Annotation修飾,而該Annotaion具有可繼承性,所以其子類也將具有@Inheritable Annotation,運行上面程序看到輸出 true
  2.如果將上面的Inheritable.java程序中的@Inherited註釋或者刪除,將會導致Inheritable Annotation不具有繼承性,運行上面程序將會輸出 false

轉自:http://blog.sina.com.cn/heyitang

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章