1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        注解知識(shí)掃盲

        共 5654字,需瀏覽 12分鐘

         ·

        2021-10-22 14:48

        一、注解

        1.1 概述

        注解(Annotation)在JDK1.5之后增加的一個(gè)新特性,注解的引入意義很大,有很多非常有名的框架,比如Hibernate、Spring等框架中都大量使用注解。注解作為程序的元數(shù)據(jù)嵌入到程序。注解可以被解析工具或編譯工具解析,此處注意注解不同于注釋(comment)。

        當(dāng)一個(gè)接口直接繼承java.lang.annotation.Annotation接口時(shí),仍是接口,而并非注解。要想自定義注解類(lèi)型,只能通過(guò)@interface關(guān)鍵字的方式,其實(shí)通過(guò)該方式會(huì)隱含地繼承.Annotation接口。

        1.2 API 摘要

        所有與Annotation相關(guān)的API摘要如下:

        (1). 注解類(lèi)型(Annotation Types) API

        注解類(lèi)型含義
        Documented表示含有該注解類(lèi)型的元素(帶有注釋的)會(huì)通過(guò)javadoc或類(lèi)似工具進(jìn)行文檔化
        Inherited表示注解類(lèi)型能被自動(dòng)繼承
        Retention表示注解類(lèi)型的存活時(shí)長(zhǎng)
        Target表示注解類(lèi)型所適用的程序元素的種類(lèi)

        (2). 枚舉(Enum) API

        枚舉含義
        ElementType程序元素類(lèi)型,用于Target注解類(lèi)型
        RetentionPolicy注解保留策略,用于Retention注解類(lèi)型

        (3). 異常和錯(cuò)誤 API

        異常/錯(cuò)誤含義
        AnnotationTypeMismatchException當(dāng)注解經(jīng)過(guò)編譯(或序列化)后,注解類(lèi)型改變的情況下,程序視圖訪問(wèn)該注解所對(duì)應(yīng)的元素,則拋出此異常
        IncompleteAnnotationException當(dāng)注解經(jīng)過(guò)編譯(或序列化)后,將其添加到注解類(lèi)型定義的情況下,程序視圖訪問(wèn)該注解所對(duì)應(yīng)的元素,則拋出此異常。
        AnnotationFormatError當(dāng)注解解析器試圖從類(lèi)文件中讀取注解并確定注解出現(xiàn)異常時(shí),拋出該錯(cuò)誤

        二、注解類(lèi)型

        前面講到注解類(lèi)型共4種,分別為Documented、Inherited、Retention、Target,接下來(lái)從jdk1.7的源碼角度,來(lái)分別加以說(shuō)明:

        2.1 Documented

        源碼:

        1@Documented
        2@Retention(RetentionPolicy.RUNTIME)
        3@Target(ElementType.ANNOTATION_TYPE)
        4public?@interface?Documented?{
        5}

        @Documented:表示擁有該注解的元素可通過(guò)javadoc此類(lèi)的工具進(jìn)行文檔化。該類(lèi)型應(yīng)用于注解那些影響客戶(hù)使用帶注釋(comment)的元素聲明的類(lèi)型。如果類(lèi)型聲明是用Documented來(lái)注解的,這種類(lèi)型的注解被作為被標(biāo)注的程序成員的公共API。

        例如,上面源碼@Retention的定義中有一行@Documented,意思是指當(dāng)前注解的元素會(huì)被javadoc工具進(jìn)行文檔化,那么在查看Java API文檔時(shí)可查看該注解元素。

        2.2 Inherited

        源碼:

        1@Documented
        2@Retention(RetentionPolicy.RUNTIME)
        3@Target(ElementType.ANNOTATION_TYPE)
        4public?@interface?Inherited?{
        5}

        @Inherited:表示該注解類(lèi)型被自動(dòng)繼承,如果用戶(hù)在當(dāng)前類(lèi)中查詢(xún)這個(gè)元注解類(lèi)型并且當(dāng)前類(lèi)的聲明中不包含這個(gè)元注解類(lèi)型,那么也將自動(dòng)查詢(xún)當(dāng)前類(lèi)的父類(lèi)是否存在Inherited元注解,這個(gè)動(dòng)作將被重復(fù)執(zhí)行知道這個(gè)標(biāo)注類(lèi)型被找到,或者是查詢(xún)到頂層的父類(lèi)。

        2.3 Retention

        源碼:

        1@Documented
        2@Retention(RetentionPolicy.RUNTIME)
        3@Target(ElementType.ANNOTATION_TYPE)
        4public?@interface?Retention?{
        5????RetentionPolicy?value();
        6}

        @Retention:表示該注解類(lèi)型的注解保留的時(shí)長(zhǎng)。當(dāng)注解類(lèi)型聲明中沒(méi)有@Retention元注解,則默認(rèn)保留策略為RetentionPolicy.CLASS。關(guān)于保留策略(RetentionPolicy)是枚舉類(lèi)型,共定義3種保留策略,如下表:

        RetentionPolicy含義
        SOURCE僅存在Java源文件,經(jīng)過(guò)編譯器后便丟棄相應(yīng)的注解
        CLASS存在Java源文件,以及經(jīng)編譯器后生成的Class字節(jié)碼文件,但在運(yùn)行時(shí)VM不再保留注釋
        RUNTIME存在源文件、編譯生成的Class字節(jié)碼文件,以及保留在運(yùn)行時(shí)VM中,可通過(guò)反射性地讀取注解

        例如,上面源碼@Retention的定義中有一行@Retention(RetentionPolicy.RUNTIME),意思是指當(dāng)前注解的保留策略為RUNTIME,即存在Java源文件,也存在經(jīng)過(guò)編譯器編譯后的生成的Class字節(jié)碼文件,同時(shí)在運(yùn)行時(shí)虛擬機(jī)(VM)中也保留該注解,可通過(guò)反射機(jī)制獲取當(dāng)前注解內(nèi)容。

        2.4 Target

        源碼:

        1@Documented
        2@Retention(RetentionPolicy.RUNTIME)
        3@Target(ElementType.ANNOTATION_TYPE)
        4public?@interface?Target?{
        5????ElementType[]?value();
        6}

        @Target:表示該注解類(lèi)型的所使用的程序元素類(lèi)型。當(dāng)注解類(lèi)型聲明中沒(méi)有@Target元注解,則默認(rèn)為可適用所有的程序元素。如果存在指定的@Target元注解,則編譯器強(qiáng)制實(shí)施相應(yīng)的使用限制。關(guān)于程序元素(ElementType)是枚舉類(lèi)型,共定義8種程序元素,如下表:

        ElementType含義
        ANNOTATION_TYPE注解類(lèi)型聲明
        CONSTRUCTOR構(gòu)造方法聲明
        FIELD字段聲明(包括枚舉常量)
        LOCAL_VARIABLE局部變量聲明
        METHOD方法聲明
        PACKAGE包聲明
        PARAMETER參數(shù)聲明
        TYPE類(lèi)、接口(包括注解類(lèi)型)或枚舉聲明

        例如,上面源碼@Target的定義中有一行@Target(ElementType.ANNOTATION_TYPE),意思是指當(dāng)前注解的元素類(lèi)型是注解類(lèi)型。

        三、內(nèi)建注解

        Java提供了多種內(nèi)建的注解,下面接下幾個(gè)比較常用的注解:@Override、@Deprecated、@SuppressWarnings這3個(gè)注解。

        3.1 @Override(覆寫(xiě))

        源碼:

        1@Target(ElementType.METHOD)
        2@Retention(RetentionPolicy.SOURCE)
        3public?@interface?Override?{
        4}

        用途:用于告知編譯器,我們需要覆寫(xiě)超類(lèi)的當(dāng)前方法。如果某個(gè)方法帶有該注解但并沒(méi)有覆寫(xiě)超類(lèi)相應(yīng)的方法,則編譯器會(huì)生成一條錯(cuò)誤信息。

        注解類(lèi)型分析:@Override可適用元素為方法,僅僅保留在java源文件中。

        3.2 @Deprecated(不贊成使用)

        源碼:

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

        用途:用于告知編譯器,某一程序元素(比如方法,成員變量)不建議使用時(shí),應(yīng)該使用這個(gè)注解。Java在javadoc中推薦使用該注解,一般應(yīng)該提供為什么該方法不推薦使用以及相應(yīng)替代方法。

        注解類(lèi)型分析:@Deprecated可適合用于除注解類(lèi)型聲明之外的所有元素,保留時(shí)長(zhǎng)為運(yùn)行時(shí)VM。

        3.3 @SuppressWarnings(壓制警告)

        源碼:

        1@Target({TYPE,?FIELD,?METHOD,?PARAMETER,?CONSTRUCTOR,?LOCAL_VARIABLE})
        2@Retention(RetentionPolicy.SOURCE)
        3public?@interface?SuppressWarnings?{
        4????String[]?value();
        5}

        用于:用于告知編譯器忽略特定的警告信息,例在泛型中使用原生數(shù)據(jù)類(lèi)型。

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

        該注解有方法value(),可支持多個(gè)字符串參數(shù),例如:

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

        前面講的@Override,@Deprecated都是無(wú)需參數(shù)的,而壓制警告是需要帶有參數(shù)的,可用參數(shù)如下:

        參數(shù)含義
        deprecation使用了過(guò)時(shí)的類(lèi)或方法時(shí)的警告
        unchecked執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告
        fallthrough當(dāng)Switch程序塊進(jìn)入進(jìn)入下一個(gè)case而沒(méi)有Break時(shí)的警告
        path在類(lèi)路徑、源文件路徑等有不存在路徑時(shí)的警告
        serial當(dāng)可序列化的類(lèi)缺少serialVersionUID定義時(shí)的警告
        finally任意finally子句不能正常完成時(shí)的警告
        all以上所有情況的警告

        3.4 對(duì)比

        3種內(nèi)建注解的對(duì)比:

        內(nèi)建注解TargetRetention
        OverrideMETHODSOURCE
        SuppressWarnings除ANNOTATION_TYPE和PACKAGE外的所有SOURCE
        Deprecated除ANNOTATION_TYPE外的所有RUNTIME

        四、 實(shí)戰(zhàn)

        4.1 自定義注解

        創(chuàng)建自定義注解,與創(chuàng)建接口有幾分相似,但注解需要以@開(kāi)頭,下面先聲明一個(gè)自定義注解(AuthorAnno.java)文件:

         1package?com.test.annotation;
        2import?java.lang.annotation.Documented;
        3import?java.lang.annotation.ElementType;
        4import?java.lang.annotation.Inherited;
        5import?java.lang.annotation.Retention;
        6import?java.lang.annotation.RetentionPolicy;
        7import?java.lang.annotation.Target;
        8
        9@Documented
        10@Target(ElementType.METHOD)
        11@Inherited
        12@Retention(RetentionPolicy.RUNTIME)
        13public?@interface?AuthorAnno{
        14????String?name();
        15????String?website()?default?"gityuan.com";
        16????int?revision()?default?1;
        17}

        自定義注解規(guī)則:

        1. 注解方法不帶參數(shù),比如name()website()

        2. 注解方法返回值類(lèi)型:基本類(lèi)型、String、Enums、Annotation以及前面這些類(lèi)型的數(shù)組類(lèi)型

        3. 注解方法可有默認(rèn)值,比如default "gityuan.com",默認(rèn)website=”gityuan.com”

        有了前面的自定義注解@AuthorAnno,那么我們便可以在代碼中使用(AnnotationDemo.java),如下:

         1package?com.test.annotation;
        2
        3public?class?AnnotationDemo?{
        4????@AuthorAnno(name="yuanhh",?website="gityuan.com",?revision=1)
        5????public?static?void?main(String[]?args)?{
        6????????System.out.println("I?am?main?method");
        7????}
        8
        9????@SuppressWarnings({?"unchecked",?"deprecation"?})
        10????@AuthorAnno(name="yuanhh",?website="gityuan.com",?revision=2)
        11????public?void?demo(){
        12????????System.out.println("I?am?demo?method");
        13????}
        14}

        由于該注解的保留策略為RetentionPolicy.RUNTIME,故可在運(yùn)行期通過(guò)反射機(jī)制來(lái)使用,否則無(wú)法通過(guò)反射機(jī)制來(lái)獲取。

        4.2 注解解析

        接下來(lái),通過(guò)反射技術(shù)來(lái)解析自定義注解@AuthorAnno,關(guān)于反射類(lèi)位于包java.lang.reflect,其中有一個(gè)接口AnnotatedElement,該接口定義了注釋相關(guān)的幾個(gè)核心方法,如下:

        返回值方法解釋
        TgetAnnotation(Class?annotationClass)當(dāng)存在該元素的指定類(lèi)型注解,則返回相應(yīng)注釋?zhuān)駝t返回null
        Annotation[]getAnnotations()返回此元素上存在的所有注解
        Annotation[]getDeclaredAnnotations()返回直接存在于此元素上的所有注解。
        booleanisAnnotationPresent(Class annotationClass)當(dāng)存在該元素的指定類(lèi)型注解,則返回true,否則返回false

        前面自定義的注解,適用對(duì)象為Method。類(lèi)Method繼承類(lèi)AccessibleObject,而類(lèi)AccessibleObject實(shí)現(xiàn)了AnnotatedElement接口,那么可以利用上面的反射方法,來(lái)實(shí)現(xiàn)解析@AuthorAnno的功能(AnnotationParser.java),內(nèi)容如下:

         1package?com.test.annotation;
        2import?java.lang.reflect.Method;
        3
        4public?class?AnnotationParser?{
        5????public?static?void?main(String[]?args)?throws?SecurityException,?ClassNotFoundException?{
        6????????String?clazz?=?"com.yuanhh.annotation.AnnotationDemo";
        7????????Method[]??demoMethod?=?AnnotationParser.class
        8????????????????.getClassLoader().loadClass(clazz).getMethods();
        9
        10????????for?(Method?method?:?demoMethod)?{
        11????????????if?(method.isAnnotationPresent(AuthorAnno.class))?{
        12?????????????????AuthorAnno?authorInfo?=?method.getAnnotation(AuthorAnno.class);
        13?????????????????System.out.println("method:?"+?method);
        14?????????????????System.out.println("name=?"+?authorInfo.name()?+?
        15?????????????????????????"?,?website=?"+?authorInfo.website()
        16????????????????????????+?"?,?revision=?"+authorInfo.revision());
        17????????????}
        18????????}
        19????}
        20}

        程序運(yùn)行的輸出結(jié)果:

        1method:?public?void?com.yuanhh.annotation.AnnotationDemo.demo()
        2name=?yuanhh?,?website=?gityuan.com?,?revision=?2
        3method:?public?static?void?com.yuanhh.annotation.AnnotationDemo.main(java.lang.String[])
        4name=?yuanhh?,?website=?gityuan.com?,?revision=?1

        這里通過(guò)反射將注解直接輸出只是出于demo,完全可以根據(jù)拿到的注解信息做更多有意義的事。

        source: //yuanfentiank789.github.io/2016/01/23/java-annotation

        喜歡,在看


        瀏覽 59
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            《少妇的激情》在线观看 | 色婷婷激情电影 | 性爱福利社| 日本wwwwxxxx泡妞 | 一级毛片学生妺 | 久一区二区三区 | 黄页网站视频在线观看 | 精品成人无码a v在线观看 | 精品无人区一区二区三区软件下载 | 人人操人人骑 |