1.注解簡介
JDK 1.5 中引入的 java.lang.annotation 包提供注解編程支持,可以讓類在編譯、類加載、運行時被讀取,並執行相應的處理。
在 Java EE應用的時候,總是免不了與各種配置文件打交道。
以Java EE中典 型的S(pring)S(truts)H(ibernate)架構來說,Spring、Struts和Hibernate這三個框架都有自己的XML格式的配置文件。
這些配置文件需要與Java源代碼保存同步,否則的話就可能出現錯誤。而且這些錯誤有可能到了運行時刻才被發現。
理想的情況是在一個地方維護這些信息就好了。其它部分所需的信息則通過自動的方式來生成。
注解的功能類似於代碼中的注釋,所不同的是注解不是提供代碼功能的說明,而是實現程序功能的重要組成部分。Java注解已經在很多框架中得到了廣泛的使用,用來簡化程序中的配置。
- 生成文檔。這是最常見的,也是java 最早提供的注解。常用的有@see @param @return 等;
- 跟蹤代碼依賴性,實現替代配置文件功能。比較常見的是spring 2.5 開始的基於注解配置。作用就是減少配置。現在的框架基本都使用了這種配置來減少配置文件的數量;
- 編譯時進行格式檢查。如@Override 放在方法前,如果你這個方法並不是覆蓋了超類方法,則編譯時就能檢查出。
2.使用注解
注解的語法比較簡單,除了@符號的使用之外,它基本與Java固有語法一致。
Java SE5內置了三種標准注解: @Override,表示當前的方法定義將覆蓋超類中的方法。
@Deprecated,使用了注解為它的元素編譯器將發出警告,因為注解@Deprecated是不贊成使用的代碼,被棄用的代碼。
@SuppressWarnings,關閉不當編譯器警告信息。 上面這三個注解多少我們都會在寫代碼的時候遇到。Java還提供了4中注解,專門負責新注解的創建。
@Target |
表示該注解可以用於什么地方,可能的ElementType參數有: CONSTRUCTOR:構造器的聲明 FIELD:域聲明(包括enum實例) LOCAL_VARIABLE:局部變量聲明 METHOD:方法聲明 PACKAGE:包聲明 PARAMETER:參數聲明 TYPE:類、接口(包括注解類型)或enum聲明 |
@Retention |
表示需要在什么級別保存該注解信息。可選的RetentionPolicy參數包括: SOURCE:注解將被編譯器丟棄 CLASS:注解在class文件中可用,但會被VM丟棄 RUNTIME:VM將在運行期間保留注解,因此可以通過反射機制讀取注解的信息。 |
@Document |
將注解包含在Javadoc中 |
@Inherited |
允許子類繼承父類中的注解 |
在一般的Java開發中,最常接觸到的可能就是@Override和@SupressWarnings這兩個注解。
使用@Override的時候只需要一個簡單的聲明即可。這種稱為標記注解(markerannotation ),它的出現就代表了某種配置語義。
而其它的注解是可以有自己的配置參數的。配置參數以名值對的方式出現。使用 @SupressWarnings的時候需要類似@SupressWarnings({"uncheck", "unused"})這樣的語法。
在括號里面的是該注解可供配置的值。由於這個注解只有一個配置參數,該參數的名稱默認為value,並且可以省略。
而花括號則表示是數組類型。在JPA中的@Table注解使用類似@Table(name = "Customer", schema = "APP")這樣的語法。
從這里可以看到名值對的用法。在使用注解時候的配置參數的值必須是編譯時刻的常量。
從某種角度來說,可以把注解看成是一個XML元素,該元素可以有不同的預定義的屬性。
而屬性的值是可以在聲明該元素的時候自行指定的。在代碼中使用注解,就相當於把一部分元數據從XML文件移到了代碼本身之中,在一個地方管理和維護。
3.開發注解
在一般的開發中,只需要通過閱讀相關的API文檔來了解每個注解的配置參數的含義,並在代碼中正確使用即可。
在有些情況下,可能會需要開發自己的注解。這在庫的開發中比較常見。注解的定義有點類似接口。
下面的代碼給出了一個簡單的描述代碼分工安排的注解。通過該注解可以在源代碼中記錄每個類或接口的分工和進度情況。
1 @Retention(RetentionPolicy.RUNTIME) 2 @Target(ElementType.TYPE) 3 public @interface Assignment { 4 String assignee(); 5 int effort(); 6 double finished() default 0; 7 }
@interface用來聲明一個注解,其中的每一個方法實際上是聲明了一個配置參數。
方法的名稱就是參數的名稱,返回值類型就是參數的類型。可以通過default來聲明參數的默認值。
在這里可以看到@Retention和@Target這樣的元注解,用來聲明注解本身的行為。
@Retention用來聲明注解的保留策略,有CLASS、RUNTIME和SOURCE這三種,分別表示注解保存在類文件、JVM運行時刻和源代碼中。
只有當聲明為RUNTIME的時候,才能夠在運行時刻通過反射API來獲取到注解的信息。
@Target用來聲明注解可以被添加在哪些類型的元素上,如類型、方法和域等。