java - 注解

1. 元注解

元注解:用在注解上的注解,java1.5后添加的4個元注解:

  • @Target
  • @Retention
  • @Documented
  • @Inherited

在java1.8又添加了兩個注解:

  • @Native
  • @Repeatable

先說明下這幾個注解.

@Target 修飾的對象范圍

取值(ElementType)有:

  • 1.CONSTRUCTOR:用于描述構(gòu)造器
  • 2.FIELD:用于描述域
  • 3.LOCAL_VARIABLE:用于描述局部變量
  • 4.METHOD:用于描述方法
  • 5.PACKAGE:用于描述包
  • 6.PARAMETER:用于描述參數(shù)
  • 7.TYPE:用于描述類、接口(包括注解類型) 或enum聲明

當(dāng)注解類型聲明中沒有@Target元注解锻全,則默認為可適用所有的程序元素咳秉。

@Retention 注解保留到哪個時期(生命周期)

取值(RetentionPoicy)有:

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

默認CLASS,可以看下源碼中提解釋:

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

@Documented 標(biāo)志可文檔化

被標(biāo)注的程序成員的公共API蜓陌,因此可以被例如javadoc此類的工具被標(biāo)注的程序成員的公共API顽爹,因此可以被例如javadoc此類的工具文檔化被標(biāo)注的程序成員的公共API丰泊,因此可以被例如javadoc此類的工具文檔化

@Inherited 將注解內(nèi)容傳遞到子類

若是方法被重寫則得不到父類方法中的注解內(nèi)容,關(guān)于該方法所有的內(nèi)容都被重新定義了.

在類上的注解會被傳遞該子類,方法也可以但重寫了則不會在傳遞給子類
再次捋清楚下:

  • 如果父類的注解是定義在類上面噪服,那么子類是可以繼承過來的
  • 如果父類的注解定義在方法上面禽拔,那么子類仍然可以繼承過來
  • 如果子類重寫了父類中定義了注解的方法索守,那么子類將無法繼承該方法的注解
  • 即子類在重寫父類中被@Inherited標(biāo)注的方法時晕窑,會將該方法連帶它上面的注解一并覆蓋掉

2.常見的Java注解

我們平時直接使用java提供幾個注解:@Override @Deprecated @SuppressWarnings @FunctionalInterface,下面逐個看下其定義

  • @Override :告知服務(wù)器,我們要覆蓋父類中的當(dāng)前方法.

     @Target(ElementType.METHOD)
     @Retention(RetentionPolicy.SOURCE)
     public @interface Override {
     }
    
  • @Deprecated :告知編譯器,某一程序元素不建議使用了

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    
  • @SuppressWarnings 忽略特定的警告
    用于告知編譯器忽略特定的警告信息卵佛,例在泛型中使用原生數(shù)據(jù)類型杨赤,編譯器會發(fā)出警告,當(dāng)使用該注解后截汪,則不會發(fā)出警告疾牲。

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

    可以接受多個參數(shù)例如:
    @SupressWarning(value={"uncheck","deprecation"})

    接受的類型:

    • all: to suppress all warnings
    • boxing: to suppress warnings relative to boxing/unboxing operations
    • cast: to suppress warnings relative to cast operations
    • dep-ann: to suppress warnings relative to deprecated annotation
    • deprecation: to suppress warnings relative to deprecation
    • fallthrough: to suppress warnings relative to missing breaks in switch statements
    • finally: to suppress warnings relative to finally block that don’t return
    • hiding: to suppress warnings relative to locals that hide variable
    • incomplete-switch: to suppress warnings relative to missing entries in a switch statement (enum case)
    • nls: to suppress warnings relative to non-nls string literals
    • null: to suppress warnings relative to null analysis
    • rawtypes: to suppress warnings relative to un-specific types when using generics on class params
    • restriction: to suppress warnings relative to usage of discouraged or forbidden references
    • serial: to suppress warnings relative to missing serialVersionUID field for a serializable class
    • static-access: to suppress warnings relative to incorrect static access
    • synthetic-access: to suppress warnings relative to unoptimized access from inner classes
    • unchecked: to suppress warnings relative to unchecked operations
    • unqualified-field-access: to suppress warnings relative to field access unqualified
    • unused: to suppress warnings relative to unused code
  • @FunctionalInterface 保證該接口是函數(shù)式接口
    用戶告知編譯器,檢查這個接口衙解,保證該接口是函數(shù)式接口阳柔,即只能包含一個抽象方法,否則就會編譯出錯蚓峦。

     @Documented
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.TYPE)
     public @interface FunctionalInterface {}
    

3. 自定義注解

Annotaion不影響程序代碼的執(zhí)行盔沫,無論增加、刪除Annotation枫匾,代碼都始終如一地執(zhí)行架诞。
也就是說:如果我們不去解析注解,它就沒什么作用和影響.
在 java.lang.Class 中末尾有4個涉及的解析注解的方法:

  • <T extends Annotation> T getAnnotation(Class<T> annotationClass)

    返回改程序元素上存在的、指定類型的注解干茉,如果該類型注解不存在谴忧,則返回null。

  • Annotation[] getAnnotations()

    返回該程序元素上存在的所有注解。

  • boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)

    判斷該程序元素上是否包含指定類型的注解沾谓,存在則返回true委造,否則返回false.

  • Annotation[] getDeclaredAnnotations()

    返回直接存在于此元素上的所有注釋。與此接口中的其他方法不同均驶,該方法將忽略繼承的注釋昏兆。(如果沒有注釋直接存在于此元素上,則返回長度為零的一個數(shù)組妇穴。)該方法的調(diào)用者可以隨意修改返回的數(shù)組爬虱;這不會對其他調(diào)用者返回的數(shù)組產(chǎn)生任何影響。

除此之外還有寫注意事項:

  • 成員類型受限:原始類型腾它,String,Class,Annotation,Enumeration
  • 注解類只有一個成員時跑筝,必須取名為value(),在使用時可以忽略成員名和賦值號(=)
  • 注解類可以沒有成員瞒滴,稱之為標(biāo)識注解

4. 實踐自定義注解

首先看下接下來要實現(xiàn)的相關(guān)類:


類結(jié)構(gòu)

FruitName 水果名稱

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FruitName {

    String value() default "";

}

FruitColor 水果顏色

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FruitColor {

    public enum Color {
        BLUE("藍色"), RED("紅色"), GREEN("綠色");

        private String name;

        public String getName() {
            return name;
        }

        Color(String name) {
            this.name = name;
        }
    }

    Color value() default Color.GREEN;
}

FruitProvider 供應(yīng)商信息

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FruitProvider {

    int id() default 1;

    String address() default "";

    String providerName() default "";

}

接下來到使用類了

Apple 使用注解

public class Apple {

    @FruitName("蘋果")
    public String name;

    @FruitColor(FruitColor.Color.GREEN)
    public String color;

    @FruitProvider(id=1001,address = "美國硅谷",providerName = "蘋果公司")
    public String  provider;

}

FruitAnnotationParser 注解解析類

public class FruitAnnotationParser {

    public static void parse() {
        Field[] fields = Apple.class.getDeclaredFields();

        for (Field field : fields) {
            if (field.isAnnotationPresent(FruitName.class)) {
                FruitName fruitName = field.getAnnotation(FruitName.class);
                String value = fruitName.value();
                System.out.println(value);

            } else if (field.isAnnotationPresent(FruitColor.class)) {
                FruitColor fruitColor = field.getAnnotation(FruitColor.class);
                FruitColor.Color color = fruitColor.value();
                System.out.println(color.getName());

            } else if (field.isAnnotationPresent(FruitProvider.class)) {
                FruitProvider provider = field.getAnnotation(FruitProvider.class);
                String address = provider.address();
                int id = provider.id();
                String providerName = provider.providerName();
                System.out.println(String.format("providerName:%s id:%d address:%s", providerName, id, address));

            }
            
        }
    }
}

測試

public class FruitTest {

    public static void main(String[] args) {
        FruitAnnotationParser.parse();
    }

}

輸出:

蘋果
綠色
providerName:蘋果公司 id:1001 address:美國硅谷

注解理解之后使用起來還是比較簡單的,解析注解的套路就那么4個,解析的過程都差不多.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曲梗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子妓忍,更是在濱河造成了極大的恐慌虏两,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件世剖,死亡現(xiàn)場離奇詭異碘举,居然都是意外死亡,警方通過查閱死者的電腦和手機搁廓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門引颈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人境蜕,你說我怎么就攤上這事蝙场。” “怎么了粱年?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵售滤,是天一觀的道長。 經(jīng)常有香客問我台诗,道長完箩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任拉队,我火速辦了婚禮弊知,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粱快。我一直安慰自己秩彤,他們只是感情好叔扼,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著漫雷,像睡著了一般瓜富。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上降盹,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天与柑,我揣著相機與錄音,去河邊找鬼蓄坏。 笑死价捧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的剑辫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼渠欺,長吁一口氣:“原來是場噩夢啊……” “哼妹蔽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挠将,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤胳岂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后舔稀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乳丰,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年内贮,在試婚紗的時候發(fā)現(xiàn)自己被綠了产园。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡夜郁,死狀恐怖什燕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竞端,我是刑警寧澤屎即,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站事富,受9級特大地震影響技俐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜统台,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一雕擂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贱勃,春花似錦捂刺、人聲如沸谣拣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽森缠。三九已至,卻和暖如春仪缸,著一層夾襖步出監(jiān)牢的瞬間贵涵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工恰画, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宾茂,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓拴还,卻偏偏與公主長得像跨晴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子片林,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容