1. 程式人生 > >Java 語言特性之 Annotation 註解

Java 語言特性之 Annotation 註解

利用 Java 的反射機制,可以在執行時獲取 Java 類的註解資訊。

註解

註解的特性

註解是 Java 5 的一個新特性,是插入程式碼中的一種註釋或者說是元資料。註解並不是程式程式碼,可以對程式作出解釋,類似於註釋。但是註解可以被相關程式讀取(例如編譯器)。

註解可以用在兩個時刻:

  • 在編譯期間,編譯工具會對註解進行處理
  • 在執行期間,使用 Java 反射機制進行處理

註解格式及用法

註解的格式:註解以 @ 開頭,後面跟註釋名,還可以加引數。

註解使用的地方:package,class,method,field 上都可以使用註解。

  • 類註解:
@MyAnnotation(name="someName",  value = "Hello World")
public class TheClass {
}
  • 方法註解:
@Override
public String toString() { // 這裡如果方法名寫錯,會報錯
	return "";
}

註解的定義

註解的定義與介面的定義相似,但是需要在 interface 關鍵字前加 @ 符號:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={
CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) public @interface Deprecated { }

元註解 meta-annotation

元註解負責註解其他註解。Java 定義了4個標準的元註解型別,用來對其它 註解型別作說明:

@Target

@Target 用於描述註解的使用位置。例如 @Target(ElementType.TYPE) 表示這個註解只能用在型別上面(比如類跟介面)。引數可以同時指定多個值,例如@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})

。ElementType 的可用值有:

  • CONSTRUCTOR:用於構造器
  • FIELD:用於欄位
  • LOCAL_VARIABLE:用於區域性變數
  • METHOD:用於方法
  • PACKAGE:用於包
  • PARAMETER:用於引數
  • TYPE:用於類、介面(包括註解型別) 或enum宣告

@Retention

@Retention 用於描述註解的生命週期。可取值有:

  • SOURCE:在原始檔中有效,編譯時丟棄
  • CLASS:在class檔案中有效,執行時丟棄
  • RUNTIME:在執行時有效

@Documented

@Documented 用於描述是否可以被 javadoc 之類的工具文件化。@Documented 是標記註解,沒有成員。

@Inherited

@Inherited 用於描述某個被標註的型別是被繼承的。如果一個使用了 @Inherited 修飾的annotation型別被用於一個class,則這個註解將被用於該class的子類。

當@Inherited 型別標註的註解的Retention是RetentionPolicy.RUNTIME,則反射API增強了這種繼承性。如果我們使用 java.lang.reflect 反射機制去查詢一個@Inherited 型別的註解時,反射程式碼檢查將展開工作:檢查class和其父類,直到發現指定的annotation型別被發現,或者到達類繼承結構的頂層。

內建註解

@Override

定義在 java.lang.Override 中,此註解只能用於修飾方法,表示重寫父類中的方法。

@Deprecated

定義在 java.lang.Deprecated 中,可以用於修飾方法、屬性或類,表示方法、屬性或類已經廢棄,不建議使用。

@SuppressWarnings

定義在 java.lang.SuppressWarnings 中,抑制編譯時的警告資訊。可以指定以下的一個或多個引數,例如 `@SuppressWarngins(value={“unchecked”, “path”}):

  • all:抑制所有警告
  • deprecate:抑制廢棄方式、屬性或類的警告
  • unchecked:抑制未檢查的警告,例如使用集合時未指定泛型
  • path:路徑、檔案不存在的警告
  • finally:抑制 finally 子句不能完成時的警告

自定義註解

使用 @interface 自定義註解時,自動繼承 java.lang.annotation.Annotation 介面。註解不能繼承其他的註解或介面。

@interface 用來宣告一個註解,其中的每一個方法實際上是聲明瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別(返回值型別只能是基本資料型別(int,float,boolean,byte,double,char,long,short)、Class、String、enum 及這些型別對應的陣列)。可以通過default來宣告引數的預設值。

定義註解的語法:

public @interface 註解名 {定義體}
  • 例如,註解使用:
@MyAnnotation(name="someName",  value = "Hello World")
public class TheClass {
}
  • 註解定義:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)

public @interface MyAnnotation {
  public String name();
  public String value();
}

訪問註解

只要是 Runtime 級別的註解,不管是類、方法、引數、變數註解都可以在執行時通過反射機制載入類後,進行訪問,具體方法可以參考 這裡

Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}