Java注解(Annotation)詳解

本篇文章講述Java中注解的相關知識卫玖。從Java中內置的注解,到自定義注解原朝,最后再介紹如何使用注解驯嘱。

一、元素據(jù)

要想理解注解(Annotation)的作用竿拆,就要先理解Java中元數(shù)據(jù)的概念宙拉。

1.元數(shù)據(jù)概念

元數(shù)據(jù)是關于數(shù)據(jù)的數(shù)據(jù)。在編程語言上下文中丙笋,元數(shù)據(jù)是添加到程序元素如方法谢澈、字段、類和包上的額外信息御板。對數(shù)據(jù)進行說明描述的數(shù)據(jù)锥忿。

2.元數(shù)據(jù)的作用

一般來說,元數(shù)據(jù)可以用于創(chuàng)建文檔(根據(jù)程序元素上的注釋創(chuàng)建文檔)怠肋,跟蹤代碼中的依賴性(可聲明方法是重載敬鬓,依賴父類的方法),執(zhí)行編譯時檢查(可聲明是否編譯期檢測)笙各,代碼分析钉答。
如下:
1) 編寫文檔:通過代碼里標識的元數(shù)據(jù)生成文檔  
2)代碼分析:通過代碼里標識的元數(shù)據(jù)對代碼進行分析  
3)編譯檢查:通過代碼里標識的元數(shù)據(jù)讓編譯器能實現(xiàn)基本的編譯檢查

3.Java平臺元數(shù)據(jù)

注解Annotation就是java平臺的元數(shù)據(jù),是 J2SE5.0新增加的功能杈抢,該機制允許在Java 代碼中添加自定義注釋数尿,并允許通過反射(reflection),以編程方式訪問元數(shù)據(jù)注釋惶楼。通過提供為程序元素(類右蹦、方法等)附加額外數(shù)據(jù)的標準方法诊杆,元數(shù)據(jù)功能具有簡化和改進許多應用程序開發(fā)領域的潛在能力,其中包括配置管理何陆、框架實現(xiàn)和代碼生成晨汹。

二贷盲、注解(Annotation)

1.注解(Annotation)的概念

注解(Annotation)在JDK1.5之后增加的一個新特性,注解的引入意義很大巩剖,有很多非常有名的框架,比如Hibernate球及、Spring等框架中都大量使用注解呻疹。注解作為程序的元數(shù)據(jù)嵌入到程序。注解可以被解析工具或編譯工具解析刽锤。

關于注解(Annotation)的作用,其實就是上述元數(shù)據(jù)的作用并思。

注意:Annotation能被用來為程序元素(類、方法宋彼、成員變量等)設置元素據(jù)弄砍。Annotaion不影響程序代碼的執(zhí)行,無論增加输涕、刪除Annotation音婶,代碼都始終如一地執(zhí)行。如果希望讓程序中的Annotation起一定的作用莱坎,只有通過解析工具或編譯工具對Annotation中的信息進行解析和處理衣式。

2.內建注解

Java提供了多種內建的注解,下面接下幾個比較常用的注解:@Override檐什、@Deprecated碴卧、@SuppressWarnings以及@FunctionalInterface這4個注解。內建注解主要實現(xiàn)了元數(shù)據(jù)的第二個作用:編譯檢查乃正。

@Override
用途:用于告知編譯器住册,我們需要覆寫超類的當前方法。如果某個方法帶有該注解但并沒有覆寫超類相應的方法烫葬,則編譯器會生成一條錯誤信息界弧。如果父類沒有這個要覆寫的方法凡蜻,則編譯器也會生成一條錯誤信息。

@Override可適用元素為方法垢箕,僅僅保留在java源文件中划栓。

**@Deprecated **
用途:使用這個注解,用于告知編譯器条获,某一程序元素(比如方法忠荞,成員變量)不建議使用了(即過時了)。
例如:
Person類中的info()方法使用@Deprecated表示該方法過時了帅掘。

public class Person {
    @Deprecated
    public void info(){
        
    }
}

調用info()方法會編譯器會出現(xiàn)警告委煤,告知該方法已過時。



注解類型分析: @Deprecated可適合用于除注解類型聲明之外的所有元素修档,保留時長為運行時碧绞。

@SuppressWarnings
用途:用于告知編譯器忽略特定的警告信息,例在泛型中使用原生數(shù)據(jù)類型吱窝,編譯器會發(fā)出警告讥邻,當使用該注解后,則不會發(fā)出警告院峡。

注解類型分析: @SuppressWarnings可適合用于除注解類型聲明和包名之外的所有元素兴使,僅僅保留在java源文件中。

該注解有方法value(),可支持多個字符串參數(shù)照激,用戶指定忽略哪種警告发魄,例如:

@SupressWarning(value={"uncheck","deprecation"})

@FunctionalInterface
用途:用戶告知編譯器,檢查這個接口励幼,保證該接口是函數(shù)式接口赏淌,即只能包含一個抽象方法啄清,否則就會編譯出錯辣卒。

注解類型分析: @FunctionalInterface可適合用于注解類型聲明,保留時長為運行時想帅。

3.元Annotation

JDK除了在java.lang提供了上述內建注解外港准,還在java.lang。annotation包下提供了6個Meta Annotation(元Annotataion)轨帜,其中有5個元Annotation都用于修飾其他的Annotation定義蚌父。其中@Repeatable專門用戶定義Java 8 新增的可重復注解毛萌。

我們先介紹其中4個常用的修飾其他Annotation的元Annotation阁将。在此之前,我們先了解如何自定義Annotation荔睹。

當一個接口直接繼承java.lang.annotation.Annotation接口時,仍是接口腊尚,而并非注解。要想自定義注解類型婿斥,只能通過@interface關鍵字的方式民宿,其實通過該方式會隱含地繼承.Annotation接口活鹰。

@Documented

@Documented用戶指定被該元Annotation修飾的Annotation類將會被javadoc工具提取成文檔只估,如果定義Annotation類時使用了@Documented修飾,則所有使用該Annotation修飾的程序元素的API文檔中將會包含該Annotation說明锌云。

例如:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

定義@Deprecated 時使用了@Documented桑涎,則任何元素使用@Deprecated修飾時,在生成API文檔時娃胆,將會包含 @Deprecated的說明
以下是String的一個過時的構造方法:

@Deprecated
public String(byte[] ascii,int hibyte,int offset, int count)

該注解實現(xiàn)了元數(shù)據(jù)的第一個功能:編寫文檔缕棵。

@Inherited

@Inherited指定被它修飾的Annotation將具有繼承性——如果某個類使用了@Xxx注解(定義該Annotation時使用了@Inherited修飾)修飾涉兽,則其子類將自動被@Xxx修飾。

@Retention

@Retention:表示該注解類型的注解保留的時長别厘。當注解類型聲明中沒有@Retention元注解触趴,則默認保留策略為RetentionPolicy.CLASS渴肉。關于保留策略(RetentionPolicy)是枚舉類型仇祭,共定義3種保留策略乌奇,如下表:


@Target

@Target:表示該注解類型的所適用的程序元素類型礁苗。當注解類型聲明中沒有@Target元注解,則默認為可適用所有的程序元素嘁信。如果存在指定的@Target元注解吱抚,則編譯器強制實施相應的使用限制考廉。關于程序元素(ElementType)是枚舉類型昌粤,共定義8種程序元素啄刹,如下表:


三、自定義注解(Annotation)

創(chuàng)建自定義注解昵时,與創(chuàng)建接口有幾分相似,但注解需要以@開頭壹甥。

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotataion{
    String name();
    String website() default "hello";
    int revision() default 1;
}

自定義注解中定義成員變量的規(guī)則:

其定義是以無形參的方法形式來聲明的句柠。即:
注解方法不帶參數(shù)溯职,比如name()帽哑,website()妻枕;
注解方法返回值類型:基本類型、String佳头、Enums康嘉、Annotation以及前面這些類型的數(shù)組類型
注解方法可有默認值亭珍,比如default "hello"肄梨,默認website=”hello”

當然注解中也可以不存在成員變量众羡,在使用解析注解進行操作時,僅以是否包含該注解來進行操作粱侣。當注解中有成員變量時齐婴,若沒有默認值柠偶,需要在使用注解時,指定成員變量的值毡证。

public class AnnotationDemo {
    @AuthorAnno(name="lvr", website="hello", revision=1)
    public static void main(String[] args) {
        System.out.println("I am main method");
    }

    @SuppressWarnings({ "unchecked", "deprecation" })
    @AuthorAnno(name="lvr", website="hello", revision=2)
    public void demo(){
        System.out.println("I am demo method");
    }
}

由于該注解的保留策略為RetentionPolicy.RUNTIME情竹,故可在運行期通過反射機制來使用秦效,否則無法通過反射機制來獲取阱州。這時候注解實現(xiàn)的就是元數(shù)據(jù)的第二個作用:代碼分析苔货。
下面來具體介紹如何通過反射機制來進行注解解析夜惭。

四铛绰、注解解析

接下來捂掰,通過反射技術來解析自定義注解。關于反射類位于包java.lang.reflect鸥昏,其中有一個接口AnnotatedElement吏垮,該接口主要有如下幾個實現(xiàn)類:Class,Constructor,Field,Method,Package。除此之外像樊,該接口定義了注釋相關的幾個核心方法生棍,如下:



因此涂滴,當獲取了某個類的Class對象柔纵,然后獲取其Field,Method等對象搁料,通過上述4個方法提取其中的注解郭计,然后獲得注解的詳細信息椒振。

public class AnnotationParser {
    public static void main(String[] args) throws SecurityException, ClassNotFoundException {
        String clazz = "com.lvr.annotation.AnnotationDemo";
        Method[]  demoMethod = AnnotationParser.class
                .getClassLoader().loadClass(clazz).getMethods();

        for (Method method : demoMethod) {
            if (method.isAnnotationPresent(MyAnnotataion.class)) {
                 MyAnnotataion annotationInfo = method.getAnnotation(MyAnnotataion.class);
                 System.out.println("method: "+ method);
                 System.out.println("name= "+ annotationInfo.name() +
                         " , website= "+ annotationInfo.website()
                        + " , revision= "+annotationInfo.revision());
            }
        }
    }
}

以上僅是一個示例庐杨,其實可以根據(jù)拿到的注解信息做更多有意義的事灵份。

以上就是本篇的全部內容填渠,喜歡就點個贊吧!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末袁铐,一起剝皮案震驚了整個濱河市揭蜒,隨后出現(xiàn)的幾起案子横浑,更是在濱河造成了極大的恐慌剔桨,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徙融,死亡現(xiàn)場離奇詭異洒缀,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門树绩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萨脑,“玉大人,你說我怎么就攤上這事饺饭∪嫡龋” “怎么了川尖?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵嘲更,是天一觀的道長。 經(jīng)常有香客問我,道長诽俯,這世上最難降的妖魔是什么仙粱? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任隔心,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘尝江。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布怜森。 她就那樣靜靜地躺著,像睡著了一般恐疲。 火紅的嫁衣襯著肌膚如雪省咨。 梳的紋絲不亂的頭發(fā)上壁公,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天囊陡,我揣著相機與錄音遏片,去河邊找鬼幢踏。 笑死,一個胖子當著我的面吹牛粗卜,可吹牛的內容都是我干的纱昧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼艘包,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了邓线?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤婿着,失蹤者是張志新(化名)和其女友劉穎徒欣,沒想到半個月后蜗字,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楼吃,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡孩锡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了口锭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椰拒。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖缚陷,靈堂內的尸體忽然破棺而出适篙,到底是詐尸還是另有隱情,我是刑警寧澤箫爷,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布嚷节,位于F島的核電站,受9級特大地震影響虎锚,放射性物質發(fā)生泄漏硫痰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一窜护、第九天 我趴在偏房一處隱蔽的房頂上張望效斑。 院中可真熱鬧,春花似錦柱徙、人聲如沸缓屠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敌完。三九已至,卻和暖如春羊初,著一層夾襖步出監(jiān)牢的瞬間蠢挡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工凳忙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留业踏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓涧卵,卻偏偏與公主長得像勤家,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子柳恐,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內容