Java注解

Java注解

Annotation键闺,注解,可理解為對代碼貼上的標(biāo)簽虽抄。

注解的定義: 跟接口類似走搁,只是多了一個@符號

public @interface TestAnnotation {}

注解的使用:

@TestAnnotation
public class Test {}

元注解,或者元標(biāo)簽有 @Retention迈窟、@Documented私植、@Target、@Inherited车酣、@Repeatable 5 種曲稼,是用來給普通的注解進行解釋說明,可以理解為標(biāo)簽的標(biāo)簽湖员。

@Retention:用來表明注解的有效時間贫悄,也就是生存時間,分為:源碼時保留破衔、編譯時保留清女、運行時保留。

它的取值如下:

  • - RetentionPolicy.SOURCE  注解只在源碼階段保留晰筛,在編譯器進行編譯時它將被丟棄忽視嫡丙。 
    - RetentionPolicy.CLASS  注解只被保留到編譯進行的時候,它并不會被加載到 JVM 中读第。 
    - RetentionPolicy.RUNTIME  注解可以保留到程序運行的時候曙博,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們怜瞒。
    
    生存周期 RUNTIME > CLASS > SOURCE.

@Documented:表明可以將注解的元素包含到Document中父泳。

@Target:目標(biāo)般哼,指定了注解應(yīng)該運用的地方,如果沒有此項惠窄,可以認(rèn)為標(biāo)簽?zāi)軌螂S便貼蒸眠,如果使用Target了,則標(biāo)簽只能貼到指定的地方了杆融。

取值如下:

ElementType.TYPE:可以給一個類型進行注解楞卡,包括類、接口脾歇、枚舉蒋腮。
ElementType.Method:可以給一個方法進行注解
ElementType.Filed:給成員變量注解
ElementType.CONSTRUCTOR:給構(gòu)造方法注解

以及其他。

@Inherited 繼承藕各,當(dāng)一個超類被Inherited注解過的A注解的話池摧,那么如果這個超類的子類沒有應(yīng)用其他注解的話,它會繼承超類的注解A激况。

@Repeatable:重復(fù)作彤,Java8 的新特性。指注解的值可以同時取多個乌逐。例如一個人的身份可以是多重的宦棺,

@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{

}

注解的屬性

注解只有成員變量,沒有成員方法黔帕,并且成員變量的定義形式需要使用無形參的方法來聲明代咸,包括 返回值+變量名+();返回值表示其類型成黄。

如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    int id();
    String msg();
}

可以設(shè)置默認(rèn)值:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    int id() default -1;
    String msg() default "Hi";
}

注解的成員屬性值的設(shè)置如下:

@TestAnnotation(id=5, msg="Hello")
public class Test {}

如果只有一個成員呐芥,則可以直接將值寫在括號中。

@TestAnn("one")

如果注解沒有屬性則連括號都可以省略奋岁。

@TestNoFiled

public class Test {}

Java預(yù)置的注解:@Override思瘟、@Deprecated、@SuppressWarnings闻伶、

@FunctionalInterface: java8新增的及汉,表示這個接口是一個函數(shù)接口抹凳,即只有一個抽象方法。

前面把注解定義好,寫好凌蔬,然后像標(biāo)簽一樣貼到代碼相應(yīng)的位置上崭歧,后續(xù)就是對標(biāo)簽的檢閱顿仇,對注解的提取角雷。

注解的提取方式是通過反射機制實現(xiàn)。

  1. 通過Class對象的方法: isAnnotationPresent()來判斷該Class對象是否使用了某個注解爆雹。
    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
  2. 通過getAnnotation()來獲取對應(yīng)的注解對象停蕉。反射中的Class/Field/Method等都可以調(diào)用該方法愕鼓。
    public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
  3. 或者是通過 getAnnotations() 方法獲取該類的所有注解對象,前面一個方法只是獲取指定的注解對象慧起。
    public Annotation[] getAnnotations()

如果Annotation對象不為null,就可以讀取它的屬性了菇晃,如下:

@Retention(RetentionPolicy.RUNTIME)
public @interface  TestAnnotation {
    int id() default -1;
    String msg() default "Hi";
}

@TestAnnotation(id=3, msg="good")
public class Test {
    public static void main(String[] args) {
        boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
        if (hasAnnotation) {
            TestAnnotation annotation = Test.class.getAnnotation(TestAnnotation.class);
            print(annotation.id());
            print(annotation.msg());
        }
    }
}

需要注意的是,如果一個注解想要在運行時被獲取蚓挤,那么它應(yīng)該有元注解:@Retention(RetentionPolicy.RUNTIME)

如果是對類的成員變量的注解進行提取解析谋旦,則需要借助反射

public @interface Check {
    int value() default 0;
}

class Test {

```
@Check(5)
int age;

@Check(value = 9)
void setAge(int age) {

}

public static void main() throws Exception{
    Field ageFiled = Test.class.getField("age");
    ageFiled.setAccessible(true);

    Check checkAnn = ageFiled.getAnnotation(Check.class);
    print(checkAnn.value());

    Method setAgeMethod = Test.class.getMethod("setAge", Integer.TYPE);
    setAgeMethod.setAccessible(true);

    if (setAgeMethod != null) {
        checkAnn = setAgeMethod.getAnnotation(Check.class);
        print(checkAnn.value());
    }
}
```
}

注解的使用場景?

注解是一系列元數(shù)據(jù)屈尼,可以提供一些數(shù)據(jù)來解釋程序代碼,并非代碼的一部分拴孤,也不會對代碼的運行有影響的脾歧。主要作用有3個:

  1. 提供信息給編譯器,編譯器可以利用注解來探測錯誤或告警信息演熟。
  2. 編譯階段的處理:某些軟件工具可以根據(jù)注解信息生成代碼鞭执、html文檔或者進行其他處理。
  3. 運行階段的處理:某些注解可以在代碼運行時候芒粹,被代碼提取出來使用兄纺。

即注解本身是不會生效或者執(zhí)行什么動作,它是被別人拿來用的化漆。被編譯器估脆、軟件工具、代碼使用座云,提供輔助信息疙赠,可以看成一種特殊的注釋信息。

例子朦拖,一個測試框架圃阳,測試代碼是否正常:

  1. 定義注解
   @Retention(RetentionPolicy.RUNTIME)
   public @interface Jiecha {}
  1. 對被測試的代碼添加注解
public class NoBug {
 @Jiecha
 public void jiafa(){
     System.out.println("1+1="+1+1);
 }

@Jiecha
 public void chufa(){
     System.out.println("6 / 0="+ 6 / 0);
 }

 public void jianfa(){
     System.out.println("1-1="+(1-1));
 }
}
  1. 抽取注解,進行測試

    public class TestTool {
    
     public static void main(String[] args) {
     NoBug nobug = new NoBug();
     
    
    ```
    Class clz = nobug.getClass();
    Method[] methods = cls.getDeclaredMethods();
    
    for (Method m : methods) {
     if (m.isAnnotationPresent(Jiecha.class) {
         try {
             m.setAccessible(true);
             m.invoke(nobug, null);
             
         } catch (Exception e) {
             print("錯誤報告");
         }
     }
    }
    ```
    }
    }
    

使用注解時璧帝,需要借助反射捍岳,但反射比較慢,所以需要謹(jǐn)慎計算時間成本睬隶。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锣夹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苏潜,更是在濱河造成了極大的恐慌晕城,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窖贤,死亡現(xiàn)場離奇詭異砖顷,居然都是意外死亡贰锁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門滤蝠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豌熄,“玉大人,你說我怎么就攤上這事物咳÷嘞眨” “怎么了?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵览闰,是天一觀的道長芯肤。 經(jīng)常有香客問我,道長压鉴,這世上最難降的妖魔是什么崖咨? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮油吭,結(jié)果婚禮上击蹲,老公的妹妹穿的比我還像新娘。我一直安慰自己婉宰,他們只是感情好歌豺,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著心包,像睡著了一般类咧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蟹腾,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天轮听,我揣著相機與錄音,去河邊找鬼岭佳。 笑死血巍,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的珊随。 我是一名探鬼主播述寡,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼叶洞!你這毒婦竟也來了鲫凶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤衩辟,失蹤者是張志新(化名)和其女友劉穎螟炫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艺晴,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡昼钻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年掸屡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片然评。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡仅财,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碗淌,到底是詐尸還是另有隱情盏求,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布亿眠,位于F島的核電站碎罚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纳像。R本人自食惡果不足惜荆烈,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爹耗。 院中可真熱鬧,春花似錦谜喊、人聲如沸潭兽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山卦。三九已至,卻和暖如春诵次,著一層夾襖步出監(jiān)牢的瞬間账蓉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工逾一, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铸本,地道東北人。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓遵堵,卻偏偏與公主長得像箱玷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子陌宿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349

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

  • 從JDK5開始锡足,Java增加了Annotation(注解),Annotation是代碼里的特殊標(biāo)記壳坪,這些標(biāo)記可以在...
    CarlosLynn閱讀 553評論 0 2
  • 兩年前爽蝴,我只是一個每天重復(fù)著單調(diào)的工作沐批,課外時間沒有任何愛好的青年纫骑。工作、生活珠插、婚姻惧磺、家庭早沒有激情。突然...
    春26閱讀 165評論 0 0
  • 請大家坐在墊子中央捻撑,面向過道的方向磨隘。雙腳向前伸直,腳背回勾顾患。雙手放于臀部旁側(cè)后側(cè)邊緣番捂,指腹點地,指尖朝前江解,手肘內(nèi)夾...
    Iris_huang閱讀 931評論 0 0
  • Angular2中包含了一個路由框架设预,我們只需要定義一個個的路徑和它對應(yīng)的組件,然后在頁面跳轉(zhuǎn)時也是用Angula...
    小孩真笨閱讀 458評論 0 0