在java的世界里面,不管是我們自己寫(xiě)代碼,亦或是看一些開(kāi)源框架的代碼掺逼,我們經(jīng)常會(huì)看到作者使用注解,注解是定義一些額外的信息或者是操作處理的手段瓤介,這就是注解的全部意義
注解的分類
Java 1.5中開(kāi)始引入的Annotation吕喘,類似于注釋解釋的一種技術(shù),我們常常使用它在代碼中來(lái)做一些注釋刑桑,并且在適當(dāng)(編譯代碼或運(yùn)行代碼等時(shí)機(jī))的時(shí)候氯质,對(duì)其進(jìn)行解釋,并且做一些額外的操作
我們先來(lái)了解一下java中已經(jīng)存在的那些注解和使用方式祠斧,然后我們?cè)龠M(jìn)行自定義注解操作和使用闻察。
內(nèi)置注解
我們?cè)陂_(kāi)發(fā)中,用得最多的Annotation莫過(guò)于@Override了梁肿。大家天天用蜓陌,可能很多人卻沒(méi)有關(guān)注過(guò)其背后的細(xì)節(jié),我們看一下它的定義:
// 方法注解吩蔑,表示此注解修飾的方法覆蓋了父類或是接口的方法
// 如果不是這樣钮热,則輸出警告
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
// 對(duì)于此注解所修飾的對(duì)象(類、域烛芬、方法等)
// 當(dāng)你使用了它們時(shí)編譯器將輸出“已廢棄”警告
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}
// 關(guān)閉警告隧期,通過(guò)給此注解的元素賦值
// 可以關(guān)閉特定警告
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
元注解
@Documented // 標(biāo)志將此注解包含至javadoc中
// 定義注解保存級(jí)別
// 1.SOURCE 源代碼注解飒责,被編譯器丟棄
// 2.CLASS 類注解,被編譯器記錄在class文件中仆潮,運(yùn)行時(shí)被VM丟棄宏蛉,在編譯時(shí)使用,屬于默認(rèn)配置
// 3.RUNTIME 被編譯器記錄在class文件中性置,運(yùn)行時(shí)可用拾并,被VM保留,所以可以在運(yùn)行時(shí)搭配反射使用
@Retention(RetentionPolicy.RUNTIME)
// 定義注解適用的目標(biāo)
// 1.TYPE Class類鹏浅,接口(包括注解類型或者enum類型)
// 2.FIELD 屬性(包括enum實(shí)例)
// 3.METHOD 方法
// 4.PARAMETER 方法參數(shù)
// 5.CONSTRUCTOR 類構(gòu)造器
// 6.LOCAL_VARIABLE 本地變量
// 7.ANNOTATION_TYPE 注解類型
// 8.PACKAGE 包
@Target(ElementType.METHOD)
// 定義繼承類型嗅义,注解也允許繼承
@Inherited
在定義元注解的時(shí)候,@Target的值都是定義為ElementType.ANNOTATION_TYPE隐砸,例如:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE) // 目標(biāo)定義為注解類型
public @interface Retention {
RetentionPolicy value();
}
自定義注解
// 定義運(yùn)行時(shí)使用策略
@Retention(RetentionPolicy.RUNTIME)
// 適用目標(biāo)是類的成員變量
@Target(ElementType.FIELD)
public @interface DBField {
String value() default ""; // default定義了默認(rèn)值之碗,此處為""
}
那么我們?nèi)绾问褂靡陨?種類型的注解呢?
舉幾個(gè)栗子
栗子1
public class ApplicantResult {
@DBField(DBConstants.sign.SHEET_ID)
long sheetId;
}
解釋:由于我們上面定義的DBField注解季希,使用是在成員變量使用褪那,所以這里我們?cè)?code>ApplicantResult類的屬性sheetId
中使用,我們發(fā)現(xiàn)為什么不是使用@DBField(value=DBConstants.sign.SHEET_ID)
呢式塌?
這里使用注解的過(guò)程中有幾個(gè)隱晦的使用規(guī)則
- 如果注解中定義了value元素
- 如果在使用注解時(shí)value是惟一需要賦值的元素
- 那么只需在括號(hào)內(nèi)給出value的值即可
- 如果沒(méi)有給相應(yīng)的注解賦值博敬,那么將使用注解中的默認(rèn)值,類似于@DBField()珊搀,value值默認(rèn)被賦予空值(即default "")
所以這里才有了我們簡(jiǎn)寫(xiě)的注解使用
栗子2
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}
對(duì)于元注解@Target冶忱,如果你希望一個(gè)注解可以作用于ElementType中的所有類型尾菇,那么就可以不使用@Target——@Deprecated就是這樣做的境析。
注解的使用
注解的使用,主要是依據(jù)@Retention的分類派诬,可以在源碼劳淆,編譯時(shí),運(yùn)行時(shí)默赂,結(jié)合不同的@Target配合使用沛鸵,我們下面主要講解一下注解有哪幾種使用場(chǎng)景
- 基于運(yùn)行時(shí)反射方式使用
@Retention(RetentionPolicy.RUNTIME)
參考我的另外一篇文章ButterKnife使用和原理 - 基于APT的注解處理工具(Java Annotation Processing Tools)