詳解Java注解( Annotation )

詳解Java注解( Annotation )

注解的定義:

注解(Annotation),也叫元數(shù)據(jù)。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對這些元素進行說明,注釋

注解的作用

  • 生成文檔

  • 代碼分析,通過代碼里的元數(shù)據(jù)來對代碼進行分析

  • 在編譯的時候進行檢查

JDK自帶的注解

在開發(fā)過程中,我們見到的JDK自帶的注解主要有三個,分別是@Override,@SuppressWarnings,@Deprecated,作用分別如下:

  • @Override

  • 主要用于標(biāo)識所用的方法是繼承自父類的方法,從而在編譯的過程中可以被編譯器檢測到,如果某個方法使用了該注解,但是方法的簽名(方法名以及參數(shù)類型)與父類不一致,則在編譯的過程中,編譯器會拋出錯誤,用于提示開發(fā)者。

  • 最常見的就是toString()方法了,該方法繼承自O(shè)bject類。如果我們在重寫該方法的時候,沒有使用該注解,然后不小心將該方法的名字寫錯如下所示:


package cn.xuhuanfeng.annotation;

public class TestAnnotation {

public static void main(String[] args) {

TestAnnotation test = new TestAnnotation();

System.out.println(test.toString());

}

public String tostring() {

return "Not true";

}

}

輸出結(jié)果為:cn.xuhuanfeng.annotation.TestAnnotation@15db9742,顯然我們可以看到,toString()方法輸出的結(jié)果顯然不是我們所期待的,有時候就會很莫名其妙了(原因是重寫toString() 方法的時候,不小心將S寫錯成了s,編譯器會理解成有一個新的方法,叫tostring(),這是正確的,所以就導(dǎo)致了調(diào)用的時候出現(xiàn)了預(yù)期之外的結(jié)果了),但是如果我們在重寫toString()方法的時候,加上@Override,這個時候,如果還是按照上面的寫法,編譯器就會告訴我們The method tostring() of type TestAnnotation must override or implement a supertype method,于是,我們很容易就能發(fā)現(xiàn)問題所在了,這是注解的好處之一,也是@Override 的作用,具體可以查看其源碼即可。

  • @Deprecated

  • 主要用于標(biāo)識該包、方法、域、變量等已經(jīng)不推薦使用了,一旦標(biāo)識了該注解,則對應(yīng)的方法、域等會劃上刪除線如下所示


@Deprecated

public void test(){

System.out.println("Deprecated");

}

  • @SuppressWarnings

  • 主要用于壓制編譯器發(fā)出的警告,該注解需要提供參數(shù),包括了unchecked all 等,分別對應(yīng)不同的壓制范圍,如:


@SuppressWarnings("all")

public void test01(){

}

自定義注解

上面我們看到了JDK中自帶的注解,雖然很有用,但是畢竟范圍有限,種類也有限,實用性不是很大,于是Java開發(fā)者為我們提供了自定義的注解,極大了擴展了該功能,下面我們就詳細來看下自定義注解的內(nèi)容。

元注解

為了使用自定義注解,首先我們需要了解一個概念:元注解,所謂的元注解,其實就是注解的注解,也就是用來表示注解的注解,JDK中包含的元注解中比較常用的有以下幾種類型: @Target , @Retention , @Documented , @Inherited ,其中前面兩種在實際開發(fā)過程中用得比較多,所以下面我們著重來介紹這兩種:

  • @Target :

  • 用于表示所標(biāo)識的注解的使用范圍,其值可以是 ElementType.PACKAGE , ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD 等,分別對應(yīng)的標(biāo)識對象為 包,構(gòu)造器,方法,域變量,也就是說,只有包含了該范圍,我們定義出來的注解才能用于對應(yīng)的域,多種類型可以組合使用,只需要使用{}包括起即可。

  • 具體使用如下:

@Target({ElementType.PACKAGE,ElementType.CONSTRUCTOR ,ElementType.METHOD, ElementType.FIELD})

  • @Retention

  • 用于標(biāo)識注解的存活周期,包括了RetentionPolicy.RUNTIME,RetentionPolicy.CLASS,RetentionPolicy.SOURCE,分別對應(yīng)存活周期為運行時,字節(jié)碼,源文件。

  • 運行時:標(biāo)識該注解存在于字節(jié)碼中,并且在運行過程中會被JVM加載,可用于反射操作。

  • 字節(jié)碼:標(biāo)識該注解存在于字節(jié)碼中,但是運行時不被JVM加載,默認(rèn)的形式。

  • 源文件:標(biāo)識該注解只存在源文件中,在編譯過程會被編譯器丟棄。

  • 具體使用如下:


@Retention(RetentionPolicy.RUNTIME)

自定義注解

學(xué)習(xí)完了元注解之后,我們就可以開始手動編寫自定義的注解了。

  • 格式:

自定義注解的書寫方式跟普通的Java類的書寫方式接近,只是將class 關(guān)鍵字替換為@interface ,如下:


@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.PACKAGE})

public @interface MyAnnotation {

}

從上面的元注解部分我們可以知道,我們定義的注解MyAnnotation 只能用于注解包,而不能用于注解方法、域等。

  • 參數(shù):

從前面的@SuppressWarnings 中我們可以知道,注解還可以帶參數(shù),不過在注解中的參數(shù)類型有點奇怪,如下:


String value();// String為參數(shù)類型 value() 整體為變量

String[] value(); // String[] 為參數(shù)類型 value() 整體為變量

默認(rèn)情況下,如果只有一個參數(shù)類型,我們將變量命名為value(),我們也可以聲明多個參數(shù)


String name();

int age(); // 其他類型依此類推

在注解中的所有參數(shù)均可以指定默認(rèn)的值,如下:


String name() default "";

int age() default -1;

由于在使用注解中我們無法標(biāo)識錯誤的情況,所以一般情況下,會將默認(rèn)類型指定為一個不合理值,用來處理注解時判斷所使用的值是合理還是不合理。

  • 使用:

定義完了一個我們的自定義注解之后,接下來我們來看下如何使用它。使用的方式跟JDK自帶的注解的方式基本一致,指定對應(yīng)的鍵值對,key為定義的參數(shù)名字,值為需要傳入的值,如果是數(shù)組類型,則傳入數(shù)組即可。


@MyAnnotation(name="xuhaunfeng",age=23)

public void test(){}

//在MyAnnotation中多增加一個變量為 String[] parents();

@MyAnnotation(name="xuhaunfeng",age=23,parents={"AA","BB"})

public void test(){}

注解的應(yīng)用

看完了上面的內(nèi)容,可能你會覺得如果注解只是上面的用法,感覺上是沒有任何作用的,確實,上面所介紹的內(nèi)容都是注解的格式、定義等,但是沒有涉及到其應(yīng)用,注解配合反射,可以實現(xiàn)很多功能,例如:ORM的實現(xiàn),框架中Annotation的應(yīng)用等,不過目前我還沒有學(xué)習(xí)到這些內(nèi)容,所以在后期學(xué)習(xí)之后將會補上,敬請期待。

參考說明

這篇文章只是我個人學(xué)習(xí)過程中的一些筆記,不帶有任何的商業(yè)目的,在學(xué)習(xí)過程中參考了很多的資料,主要參考深入理解Java:注解(Annotation)自定義注解入門 By竹子,在此對竹子表示感謝。如果本文涉及的一些內(nèi)容有一些版權(quán)爭議,還請與我聯(lián)系。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容