Java註解是JSR 250的規範,在jdk1.5版本以後引入。java
Annotation(註解)是JDK1.5及之後版本引入的。它能夠用於建立文檔,跟蹤代碼中的依賴性,甚至執行基本編譯時檢查。註解是以‘@註解名’在代碼中存在的,根據註解參數的個數,咱們能夠將註解分爲:標記註解、單值註解、完整註解三類。它們都不會直接影響到程序的語義,只是做爲註解(標識)存在,咱們能夠經過反射機制編程實現對這些元數據(用來描述數據的數據)的訪問。另外,你能夠在編譯時選擇代碼裏的註解是否只存在於源代碼級,或者它也能在class文件、或者運行時中出現(SOURCE/CLASS/RUNTIME)。編程
若是要對於元數據的做用進行分類,尚未明確的定義,不過咱們能夠根據它所起的做用,大體可分爲三類:測試
編寫文檔:經過代碼裏標識的元數據生成文檔。編碼
代碼分析:經過代碼裏標識的元數據對代碼進行分析。spa
編譯檢查:經過代碼裏標識的元數據讓編譯器能實現基本的編譯檢查code
用@Target指定ElementType屬性對象
public enum ElementType { // 用於類,接口,枚舉但不能是註解 TYPE, // 字段上,包括枚舉值 FIELD, // 方法,不包括構造方法 METHOD, // 方法的參數 PARAMETER, // 構造方法 CONSTRUCTOR, // 本地變量或catch語句 LOCAL_VARIABLE, // 註解類型(無數據) ANNOTATION_TYPE, // Java包 PACKAGE }
舉例:繼承
// 限制註解使用範圍 @Target({ElementType.METHOD,ElementType.CONSTRUCTOR}) public @interface Greeting { // 使用枚舉類型 public enum FontColor { BLUE,RED,GREEN }; String name(); FontColor fontColor() default FontColor.RED; }
在Java編譯器編譯時,它會識別在源代碼裏添加的註解是否還會保留,這就是RetentionPolicy。下面是Java定義的RetentionPolicy枚舉:接口
public enum RetentionPolicy { // 此類型會被編譯器丟棄 SOURCE, // 此類型註解會保留在class文件中,但JVM會忽略它 CLASS, // 此類型註解會保留在class文件中,JVM會讀取它 RUNTIME }
編譯器的處理有三種策略:開發
將註解保留在編譯後的類文件中,並在第一次加載類時讀取它;
將註解保留在編譯後的類文件中,可是在運行時忽略它;
按照規定使用註解,可是並不將它保留到編譯後的類文件中。
// 讓保持性策略爲運行時態,即將註解編碼到class文件中,讓虛擬機讀取 @Retention(RetentionPolicy.RUNTIME) public @interface Greeting { // 使用枚舉類型 public enum FontColor { BLUE,RED,GREEN }; String name(); FontColor fontColor() default FontColor.RED; }
Java提供的Documented元註解跟Javadoc的做用是差很少的,其實它存在的好處是開發人員能夠定製Javadoc不支持的文檔屬性,並在開發中應用。它的使用跟前兩個也是同樣的,簡單代碼示例以下:
// 讓它定製文檔化功能 // 使用此註解時必須設置RetentionPolicy爲RUNTIME @Documented public @interface Greeting { // 使用枚舉類型 public enum FontColor { BLUE,RED,GREEN }; String name(); FontColor fontColor() default FontColor.RED; }
// 讓它容許繼承,可做用到子類 @Inherited public @interface Greeting { // 使用枚舉類型 public enum FontColor { BLUE,RED,GREEN }; String name(); FontColor fontColor() default FontColor.RED; }
屬於重點,在系統中用到註解權限時很是有用,能夠精確控制權限的粒度
注意:要想使用反射去讀取註解,必須將Retention的值選爲Runtime
import java.lang.annotation.Annotation; import java.lang.reflect.Method; //讀取註解信息 public class ReadAnnotationInfoTest { public static void main(String[] args) throws Exception { // 測試AnnotationTest類,獲得此類的類對象 Class c = Class.forName("com.iwtxokhtd.annotation.AnnotationTest"); // 獲取該類全部聲明的方法 Method[] methods = c.getDeclaredMethods(); // 聲明註解集合 Annotation[] annotations; // 遍歷全部的方法獲得各方法上面的註解信息 for (Method method : methods) { // 獲取每一個方法上面所聲明的全部註解信息 annotations = method.getDeclaredAnnotations(); // 再遍歷全部的註解,打印其基本信息 System.out.println(method.getName()); for (Annotation an : annotations) { System.out.println("方法名爲:" + method.getName() + "其上面的註解爲:" + an.annotationType().getSimpleName()); Method[] meths = an.annotationType().getDeclaredMethods(); // 遍歷每一個註解的全部變量 for (Method meth : meths) { System.out.println("註解的變量名爲:" + meth.getName()); } } } } }