Java的註解非可是一種標記,仍是一種特殊的類型,而且擁有專門的類型定義。前面介紹的五種內置註解,均可以找到對應的類型定義代碼,例如查看註解@Override的源碼,發現它的代碼定義是下面這樣的:html
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override {}
又如註解@FunctionalInterface,它的源碼定義與之相似:java
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {}
乍看過去,註解的定義竟與接口有幾分相像,接口的類型名稱是「interface」,而註解的類型名稱是「@interface」,僅僅多了一個@符號。此外,內置註解的定義代碼上方多出了好幾個其它註解,包括@Target、@Retention、@Documented等等,這三個註解連同@Inherited組成了Java的「元註解」。四個元註解的做用是給新定義的註解添加修飾,標明新註解什麼能幹什麼不能幹,比如給一個戰士配備各式各樣的武器,使得他更適合在某種環境之中做戰。接下來就對四種元註解分別進行詳細介紹:程序員
一、@Documented
該註解表示它修飾的註解將被收錄到Java的開發文檔中,這意味着程序員編碼時的快捷提示會出現已收入的註解。
所謂的快捷提示,指的是每當程序員輸入少數幾個字符並按下「Alt+/」時,eclipse就自動彈出以這幾個字符開頭的詞彙列表,以便程序員迅速選擇想要的詞彙,從而加快編碼速度。好比,程序員在某個空行輸入字母M,而後按下組合鍵「Alt+/」,eclipse會彈出以M打頭的詞彙列表,包括數學函數庫Math、映射Map、方法Method等等,此時點擊「Method」這行提示,eclipse便自動把M補齊成爲Method。
添加了@Documented的註解如@FunctionalInterface,就會出如今這種提示列表;而@Override沒被@Documented所修飾,就不會在提示列表中出現。故而程序員在一個空行輸入符號@,而後按下組合鍵「Alt+/」,彈出的詞彙列表中能找到「@FunctionalInterface」,卻不能找到「@Override」了。eclipse
二、@Target
該註解表示它修飾的註解將做用於哪一類的代碼實體,例如ElementType.METHOD規定@Override對方法有效,而ElementType.TYPE規定@FunctionalInterface對類型有效。更多的ElementType取值說明見下:
TYPE:類型,包括類、接口和枚舉。
FIELD:字段,即類的屬性。
METHOD:方法,但不包含構造方法。
PARAMETER:方法的參數。
CONSTRUCTOR:構造方法。
LOCAL_VARIABLE:局部變量。
ANNOTATION_TYPE:註解類型。
PACKAGE:包。ide
三、@Retention
該註解表示它修飾的註解將被編譯器保留至哪一個階段,例如「@Retention(RetentionPolicy.SOURCE)」規定編譯器只在編碼階段保留@Override,而「@Retention(RetentionPolicy.RUNTIME)」規定編譯器直到運行階段仍然保留@FunctionalInterface。更多的RetentionPolicy取值說明見下:
SOURCE:只在編碼階段保留。
CLASS:保留在編譯生成的class文件中,但不在運行時保留。這樣從class文件反編譯出來的源碼仍可找到它所修飾的註解。
RUNTIME:一直保留至運行階段。這樣修飾後的註解可經過反射技術讀取得到,以便代碼在運行時動態校驗註解。函數
四、@Inherited
該註解表示它修飾的註解將容許被子類所繼承。
一般狀況下,一個註解加在某個類上面的話,它只對當前類有效,而對當前類的子類無效。假若程序員但願該註解同時做用於當前類及其全部子類,則須要給這個註解的定義代碼添加@Inherited修飾,表示該註解的做用範圍擴展到當前類派生出來的子類。編碼
更多Java技術文章參見《Java開發筆記(序)章節目錄》spa