天天看點

Java Annotation詳解(一): 了解和使用Annotation

jdk1.5之後,引入了中繼資料的概念,也就是annotation(注釋),其實它是代碼裡的特殊标記,這些标記可以再編譯、類加載、運作時被讀取,并執行相應的處理。

中繼資料的作用:

如果要對于中繼資料的作用進行分類,目前還沒有明确的定義,不過我們可以根據它所起的作用,大緻可分為三類:

1.  編寫文檔:通過代碼裡辨別的中繼資料生成文檔。

2.  代碼分析:通過代碼裡辨別的中繼資料對代碼進行分析。

3.  編譯檢查:通過代碼裡辨別的中繼資料讓編譯器能實作基本的編譯檢查。

一、 系統内建的annotation:

    @override 覆寫的annotation

注釋能實作編譯時檢查,你可以為你的方法添加該注釋,以聲明該方法是用于覆寫父類中的方法。如果該方法不是覆寫父類的方法,将會在編譯時報錯。例如我們為某類重寫tostring()方法卻寫成了tostring(),并且我們為該方法添加了@override注釋,則會提示編譯錯誤。

     @deprecated 不贊成使用的annotation

其作用是對不應該在使用的方法添加注釋,當程式設計人員使用這些方法時,将會在編譯時顯示提示資訊,不推薦在使用該方法或該類。

    @suppresswarnings 壓制安全警告的annotation

與前兩個注釋有所不同,你需要添加一個參數才能正确使用,這些參數值都是已經定義好了的,我們選擇性的使用就好了,參數如下:

deprecation   使用了過時的類或方法時的警告

unchecked  執行了未檢查的轉換時的警告,例如當使用集合時沒有用泛型 (generics) 來指定集合儲存的類型

fallthrough   當 switch 程式塊直接通往下一種情況而沒有 break 時的警告

path   在類路徑、源檔案路徑等中有不存在的路徑時的警告

serial 當在可序列化的類上缺少 serialversionuid 定義時的警告

finally    任何 finally 子句不能正常完成時的警告

all 關于以上所有情況的警告

在為@suppresswarnings設定注釋資訊的時候,是以key-value的形式出現的,是以以上的@suppresswarnings也可以直接使用,是以@suppresswarnings可以使用”value={"unchecked","deprecation"}“的方式來設定。

上面,我們将 注釋掉,編譯後,會出現警告提示:

---------- javac ----------

注: suppresswarningsannotationdemo03.java使用或覆寫了已過時的 api。

注: 有關詳細資訊, 請使用 -xlint:deprecation 重新編譯。

注: suppresswarningsannotationdemo03.java使用了未經檢查或不安全的操作。

注: 有關詳細資訊, 請使用 -xlint:unchecked 重新編譯。

打開@suppresswarnings注釋,再次編譯,發現,警告已被抑制。

二、 自定義annotation

定義簡單的annotation形式:

[public] @interface annotation名稱{

        資料類型  變量名稱();

}

例如:

之後,就可以直接使用@annotation名稱:

此時,就表示在demo類上使用annotation。

還可以向annotation中設定變量,使用變量接受參數。

在使用的時候,必須清楚的指定變量的名稱,變量的内容:

或者使用明确的标記,表示内容賦給哪個參數:

以上的參數,是要賦給value屬性的。既然可以設定一個參數,則也就可以同時設定多個參數。

此annotation在使用時,需要設定兩個參數,一個key,一個value。

當然,我們可以設定數組進去,@suppresswarnings就使用了數組。

接收内容本身是一個數組類型,要傳遞數組。

以上的定義annotation都未指定屬性的預設值,必須在使用時設定。 其實,也可以直接使用default來定義預設值:

在實際的操作中,對于一個annotation而言,有時候會固定其取值範圍,隻能使用固定的幾個值。那麼這時候實際上就需要依靠枚舉:

三、 限定注釋使用範圍target

當我們的自定義注釋不斷的增多也比較複雜時,就會導緻有些開發人員使用錯誤,主要表現在不該使用該注釋的地方使用。為此,java提供了一個elementtype枚舉類型來控制每個注釋的使用範圍,比如說某些注釋隻能用于普通方法,而不能用于構造函數等。下面是java定義的elementtype枚舉:

想要使用elementtype,隻需要為注釋添加@target即可:

正如上面代碼所展示的,我們隻允許greeting注釋标注在普通方法和構造函數上,使用在包申明、類名等時,會提示錯誤資訊。

四、 retention和retentionpolicy,注釋保持性政策

retentionpolicy的使用方法的簡單代碼示例如下:

@retention(retentionpolicy.runtime)

而,在retentionpolicy的三個範圍中,最需要注意的就是runtime範圍,因為在執行的時候起作用。

我們看下内建的annotation的retentionpolicy:

@override定義采用的是@retention(value=source),隻能在源檔案中出現。

@deprecated定義采用的是@retention(value=runtime),可以在執行時出現。

@suppresswarnings定義采用的是@retention(value=source),隻能在源檔案中出現。

五、 文檔化功能

java提供的documented元注釋跟javadoc的作用是差不多的,其實它存在的好處是開發人員可以定制javadoc不支援的文檔屬性,并在開發中應用。它的使用跟前兩個也是一樣的,簡單代碼示例如下:

成功後,在使用此annotation的時候,可以增加一些資訊進去:

之後,在生成jdk文檔的時候,使用@document修飾的方法将被注釋下來。

六、 标注繼承

繼承應該是java提供的最複雜的一個元注釋了,它的作用是控制注釋是否會影響到子類(一個annotation是否可以被繼承下來),簡單代碼示例如下:

使用該注釋,标注一個父類person:

按照所解釋的,使用inherited聲明的annotation是可以被子類繼承下來的: