java進階之注解

Java注解(Annotation)又稱Java標注名段,是JDK5中引入的一種注釋機制躏惋。Annotation其實是代碼中的特殊標記红氯,這些標記可以在編譯框咙、類加載、運行時被讀取痢甘,并執(zhí)行相應(yīng)的處理喇嘱。通過使用注解,開發(fā)人員可以在不改變原有邏輯的情況下塞栅,在源文件中嵌入一些補充信息者铜。

1.注解的聲明

與聲明一個"Class"不同的是,注解的聲明使用 @interface 關(guān)鍵字。一個注解的聲明如下:

public @interface AnnotationTest {}

2.元注解

在定義注解時作烟,注解類也能夠使用其他的注解聲明愉粤。對注解類型進行注解的注解類,我們稱之為 meta annotation(元注解)拿撩。一般情況下衣厘,我們在定義自定義注解時,需要指定的元注解主要有兩個:@Retention压恒、@Target影暴,對于@Documented和@Inherited用的相對較少,下面我們看下這些元注解探赫。

2.1 注解@Retention

@Retention只能用于修飾Annotation定義型宙,用于指定被修飾的Annotation可以保留多長時間。

Annotation的保留有三種方式:

package java.lang.annotation;

public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME;

    private RetentionPolicy() {
    }
}
  • RetentionPolicy.SOURCE: 標記的注解僅保留到源碼級別中伦吠,并被編譯器忽略妆兑。
  • RetentionPolicy.CLASS: 標記的注解在編譯時由編譯器保留,但 Java 虛擬機(JVM)會忽略毛仪。
  • RetentionPolicy.RUNTIME: 標記的注解由 JVM 保留搁嗓,因此運行時環(huán)境可以使用它。

@Retention 三個值中 SOURCE < CLASS < RUNTIME潭千,即CLASS包含了SOURCE谱姓,RUNTIME包含SOURCE借尿、
CLASS刨晴。

示例:

@Retention(RetentionPolicy.RUNTIME)  //注解保留在運行時
public @interface AnnotationTest {
}

2.2 注解@Target

@Target注解標記另一個注解,以限制可以應(yīng)用注解的Java元素類型路翻。目標注解指定以下元素類型之一作為其值:

package java.lang.annotation;

public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE;

    private ElementType() {
    }
}
  • ElementType.TYPE: 可以應(yīng)用于類的任何元素狈癞。
  • ElementType.FIELD: 可以應(yīng)用于字段或?qū)傩浴?/li>
  • ElementType.METHOD: 可以應(yīng)用于方法級注解。
  • ElementType.PARAMETER: 可以應(yīng)用于方法的參數(shù)茂契。
  • ElementType.CONSTRUCTOR: 可以應(yīng)用于構(gòu)造函數(shù)蝶桶。
  • ElementType.LOCAL_VARIABLE: 可以應(yīng)用于局部變量。
  • ElementType.ANNOTATION_TYPE: 可以應(yīng)用于注解類型掉冶。
  • ElementType.PACKAGE: 可以應(yīng)用于包聲明真竖。
  • ElementType.TYPE_PARAMETER:可以用于類型參數(shù)聲明(1.8新加入)
  • ElementType.TYPE_USE:可以用于類型使用聲明(1.8新加入)

示例:

@Retention(RetentionPolicy.RUNTIME) //注解保留在運行時
@Target(ElementType.METHOD) //只可以用于方法級注解
public @interface AnnotationTest {
}

2.3 注解@Documented

@Documented注解用于被javadoc工具提取成文檔

@Documented
public @interface AnnotationTest {
}

2.4 注解@Inherited

@Inherited表示允許子類繼承父類中定義的注解。

示例:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited   // 1
public @interface Inheritable {
}

我們對Inheritable注解添加元注解@Inherited厌小,則Inheritable注解具有繼承性恢共。

@Inheritable
public class Base {
}

我們Base類使用了@Inheritable注解,其子類也將使用@Inheritable注解

public class ChildAnnotation extends Base {
    public static void main(String[] args) {
        System.out.println(ChildAnnotation.class.isAnnotationPresent(Inheritable.class));
    }
}

我們的ChildAnnotation類繼承自Base類璧亚,然后運行結(jié)果為true讨韭。
如果我們將上面 “1”注釋掉,那么@Inheritable將不具有繼承性,其運行結(jié)果為false透硝。

3.注解元素類型

通過上述對@AnnotationTest注解的定義狰闪,我們了解了注解定義的過程,由于@AnnotationTest內(nèi)部沒有定義其他元素濒生,所以@AnnotationTest也稱為標記注解埋泵,但在自定義注解中,一般都會包含一些元素以表示某些值甜攀,方便處理器使用秋泄,這點在下面的例子將會看到:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AnnotationTest {
    String value() default "";
}

我們聲明了一個String類型的value元素,默認是空字符串规阀,須注意到對應(yīng)任何元素的聲明應(yīng)采用方法的聲明方式恒序,同時可選擇使用default提供默認值。

@AnnotationTest(value = "123")
public class Test {
}

而對于上面沒有使用default默認值谁撼,我們在使用的時候就必須去指定@AnnotationTest(value = "123")否則編譯器會報錯歧胁, 使用了default默認值就可以直接使用@AnnotationTest可以去管value

注解支持的元素數(shù)據(jù)類型除了上述的String,還支持如下數(shù)據(jù)類型:

  • 所有基本類型(int,float,boolean,byte,double,char,long,short)
  • String
  • Class
  • enum
  • Annotation
  • 上述類型的數(shù)組

倘若使用了其他數(shù)據(jù)類型厉碟,編譯器將會丟出一個編譯錯誤喊巍,注意,聲明注解元素時可以使用基本類型但不允許使用任何包裝類型箍鼓,同時還應(yīng)該注意到注解也可以作為元素的類型崭参,也就是嵌套注解。

4.注意

編譯器對默認值的限制

編譯器對元素的默認值有嚴格的要求款咖。元素要么具有默認值何暮,要么在使用注解時提供元素的值。其次铐殃,對于非基本類型的元素海洼,無論是在源代碼中聲明,還是在注解接口中定義默認值富腊,都不能以null作為值坏逢,這就是限制,但造成一個元素的存在或缺失狀態(tài)赘被,因為每個注解的聲明中是整,所有的元素都存在,并且都具有相應(yīng)的值民假,為了繞開這個限制浮入,只能定義一些特殊的值,例如空字符串或負數(shù)阳欲,表示某個元素不存在舵盈。

注解不支持繼承

注解是不支持繼承的陋率,因此不能使用關(guān)鍵字extends來繼承某個@interface,但注解在編譯后秽晚,編譯器會自動繼承java.lang.annotation.Annotation接口瓦糟,即使Java的接口可以實現(xiàn)多繼承,但定義注解時依然無法使用extends關(guān)鍵字繼承@interface赴蝇。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菩浙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子句伶,更是在濱河造成了極大的恐慌劲蜻,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件考余,死亡現(xiàn)場離奇詭異先嬉,居然都是意外死亡,警方通過查閱死者的電腦和手機楚堤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門疫蔓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人身冬,你說我怎么就攤上這事衅胀。” “怎么了酥筝?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵滚躯,是天一觀的道長。 經(jīng)常有香客問我嘿歌,道長掸掏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任搅幅,我火速辦了婚禮阅束,結(jié)果婚禮上呼胚,老公的妹妹穿的比我還像新娘茄唐。我一直安慰自己,他們只是感情好蝇更,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布沪编。 她就那樣靜靜地躺著,像睡著了一般年扩。 火紅的嫁衣襯著肌膚如雪蚁廓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天厨幻,我揣著相機與錄音相嵌,去河邊找鬼腿时。 笑死,一個胖子當著我的面吹牛饭宾,可吹牛的內(nèi)容都是我干的批糟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼看铆,長吁一口氣:“原來是場噩夢啊……” “哼徽鼎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弹惦,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤否淤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棠隐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體石抡,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年助泽,在試婚紗的時候發(fā)現(xiàn)自己被綠了汁雷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡报咳,死狀恐怖侠讯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情暑刃,我是刑警寧澤厢漩,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站岩臣,受9級特大地震影響溜嗜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜架谎,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一炸宵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谷扣,春花似錦土全、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至末秃,卻和暖如春概页,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背练慕。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工惰匙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留技掏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓项鬼,卻偏偏與公主長得像零截,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子秃臣,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359