Java元註解作用及使用-7

元註解是負責對其它註解進行說明的註解,自定義註解時可以使用元註解。Java 5 定義了 4 個註解,分別是 @Documented、@Target、@Retention 和 @Inherited。Java 8 又增加了 @Repeatable 和 @Native 兩個註解。這些註解都可以在 java.lang.annotation 包中找到。下面主要介紹每個元註解的作用及使用。


本節示例會用到自定義註解,不瞭解可先閱讀學習《Java自定義註解》一節。

@Documented

@Documented 是一個標記註解,沒有成員變量。用 @Documented 註解修飾的註解類會被 JavaDoc 工具提取成文檔。默認情況下,JavaDoc 是不包括註解的,但如果聲明註解時指定了 @Documented,就會被 JavaDoc 之類的工具處理,所以註解類型信息就會被包括在生成的幫助文檔中。
下面通過示例來了解它的用法,代碼如下所示。

例 1

<code>

@Documented

@Target

({

ElementType

.TYPE

,

ElementType

.METHOD

})

public

@interface

MyDocumented {

public

String

value

()

default

"這是

@Documented

註解";}/<code>

測試類:

<code>  

class

DocumentedTest

{

public

String

Test

()

{

return

"C語言中文網Java教程"

; }}/<code>

打開 Java 文件所在的目錄,分別輸入如下兩條命令行:

<code>

javac

MyDocumented

.java

DocumentedTest

.java

javadoc

-d

doc

MyDocumented

.java

DocumentedTest

.java

/<code>

運行成功後,打開生成的幫助文檔,可以看到在類和方法上都保留了 MyDocument 的註解信息。如下圖所示:

Java元註解作用及使用-7


Java元註解作用及使用-7

@Target

@Target 註解用來指定一個註解的使用範圍,即被 @Target 修飾的註解可以用在什麼地方。@Target 註解有一個成員變量(value)用來設置適用目標,value 是 java.lang.annotation.ElementType 枚舉類型的數組,下表為 ElementType 常用的枚舉常量。

名稱說明CONSTRUCTOR用於構造方法FIELD用於成員變量(包括枚舉常量)LOCAL_VARIABLE用於局部變量METHOD用於方法PACKAGE用於包PARAMETER用於類型參數(JDK 1.8新增)TYPE用於類、接口(包括註解類型)或 enum 聲明

例 2

自定義一個 MyTarget 註解,使用範圍為方法,代碼如下所示。

<code>

@Target

({ ElementType.METHOD })public

@interface

MyTarget {}class Test {

@MyTarget

String name;}/<code>

如上代碼第 6 行會編譯錯誤,錯誤信息為:

The annotation @MyTarget is disallowed for this location

提示此位置不允許使用註解 @MyDocumented,@MyTarget 不能修飾成員變量,只能修飾方法。

@Retention

@Retention 用於描述註解的生命週期,也就是該註解被保留的時間長短。@Retention 註解中的成員變量(value)用來設置保留策略,value 是 java.lang.annotation.RetentionPolicy 枚舉類型,RetentionPolicy 有 3 個枚舉常量,如下所示。

  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在 class 文件中有效(即 class 保留)
  3. RUNTIME:在運行時有效(即運行時保留)


生命週期大小排序為 SOURCE < CLASS < RUNTIME,前者能使用的地方後者一定也能使用。如果需要在運行時去動態獲取註解信息,那隻能用 RUNTIME 註解;如果要在編譯時進行一些預處理操作,比如生成一些輔助代碼(如 ButterKnife),就用 CLASS 註解;如果只是做一些檢查性的操作,比如 @Override 和 @SuppressWarnings,則可選用 SOURCE 註解。

@Inherited

@Inherited 是一個標記註解,用來指定該註解可以被繼承。使用 @Inherited 註解的 Class 類,表示這個註解可以被用於該 Class 類的子類。就是說如果某個類使用了被 @Inherited 修飾的註解,則其子類將自動具有該註解。

例 3

創建一個自定義註解,代碼如下所示:

<code>

@Target

({ ElementType.TYPE })

@Inherited

@Retention

(RetentionPolicy.RUNTIME)public

@interface

MyInherited {}/<code>

測試類代碼如下:

<code>  

class

TestA

{

public

static

void

main

(String[] args)

{ System.out.println(TestA

.

class

.

getAnnotation

(

MyInherited

.

class

))

; System.out.println(TestB

.

class

.

getAnnotation

(

MyInherited

.

class

))

; System.out.println(TestC

.

class

.

getAnnotation

(

MyInherited

.

class

))

; }}

class

TestB

extends

TestA

{}

class

TestC

extends

TestB

{}/<code>

運行結果為:

@MyInherited()@MyInherited()@MyInherited()

@Repeatable

@Repeatable 註解是 Java 8 新增加的,它允許在相同的程序元素中重複註解,在需要對同一種註解多次使用時,往往需要藉助 @Repeatable 註解。Java 8 版本以前,同一個程序元素前最多隻能有一個相同類型的註解,如果需要在同一個元素前使用多個相同類型的註解,則必須使用註解“容器”。

例 4

Java 8 之前的做法:

<code>

public

@

interface

Roles

{

Role[]

roles

(

)

;}

public

@

interface

Roles

{

Role[]

value

(

)

;}

public

class

RoleTest

{ @Roles(roles = {@Role(roleName =

"role1"

), @Role(roleName =

"role2"

)})

public

String

doString

(

)

{

return

"這是C語言中國網Java教程"

; }}/<code>

Java 8 之後增加了重複註解,使用方式如下:

<code>

public

Roles { Role[] value();}

public

Role { String roleName();}

public

class

RoleTest

{

public

String doString(){

return

"這是C語言中文網Java教程"

; }}/<code>

不同的地方是,創建重複註解 Role 時加上了 @Repeatable 註解,指向存儲註解 Roles,這樣在使用時就可以直接重複使用 Role 註解。從上面例子看出,使用 @Repeatable 註解更符合常規思維,可讀性強一點。
兩種方法獲得的效果相同。重複註解只是一種簡化寫法,這種簡化寫法是一種假象,多個重複註解其實會被作為“容器”註解的 value 成員的數組元素處理。

@Native

使用 @Native 註解修飾成員變量,則表示這個變量可以被本地代碼引用,常常被代碼生成工具使用。對於 @Native 註解不常使用,瞭解即可。


分享到:


相關文章: