在java的世界里面,不管是我們自己寫代碼,亦或是看一些開源框架的代碼,我們經(jīng)常會看到作者使用注解,注解是定義一些額外的信息或者是操作處理的手段,這就是注解的全部意義
注解的分類
Java 1.5中開始引入的Annotation,類似于注釋解釋的一種技術(shù),我們常常使用它在代碼中來做一些注釋,并且在適當(編譯代碼或運行代碼等時機)的時候,對其進行解釋,并且做一些額外的操作
我們先來了解一下java中已經(jīng)存在的那些注解和使用方式,然后我們再進行自定義注解操作和使用。
內(nèi)置注解
我們在開發(fā)中,用得最多的Annotation莫過于@Override了。大家天天用,可能很多人卻沒有關(guān)注過其背后的細節(jié),我們看一下它的定義:
// 方法注解,表示此注解修飾的方法覆蓋了父類或是接口的方法
// 如果不是這樣,則輸出警告
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
// 對于此注解所修飾的對象(類、域、方法等)
// 當你使用了它們時編譯器將輸出“已廢棄”警告
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}
// 關(guān)閉警告,通過給此注解的元素賦值
// 可以關(guān)閉特定警告
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
元注解
@Documented // 標志將此注解包含至javadoc中
// 定義注解保存級別
// 1.SOURCE 源代碼注解,被編譯器丟棄
// 2.CLASS 類注解,被編譯器記錄在class文件中,運行時被VM丟棄,在編譯時使用,屬于默認配置
// 3.RUNTIME 被編譯器記錄在class文件中,運行時可用,被VM保留,所以可以在運行時搭配反射使用
@Retention(RetentionPolicy.RUNTIME)
// 定義注解適用的目標
// 1.TYPE Class類,接口(包括注解類型或者enum類型)
// 2.FIELD 屬性(包括enum實例)
// 3.METHOD 方法
// 4.PARAMETER 方法參數(shù)
// 5.CONSTRUCTOR 類構(gòu)造器
// 6.LOCAL_VARIABLE 本地變量
// 7.ANNOTATION_TYPE 注解類型
// 8.PACKAGE 包
@Target(ElementType.METHOD)
// 定義繼承類型,注解也允許繼承
@Inherited
在定義元注解的時候,@Target的值都是定義為ElementType.ANNOTATION_TYPE,例如:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE) // 目標定義為注解類型
public @interface Retention {
RetentionPolicy value();
}
自定義注解
// 定義運行時使用策略
@Retention(RetentionPolicy.RUNTIME)
// 適用目標是類的成員變量
@Target(ElementType.FIELD)
public @interface DBField {
String value() default ""; // default定義了默認值,此處為""
}
那么我們?nèi)绾问褂靡陨?種類型的注解呢?
舉幾個栗子
栗子1
public class ApplicantResult {
@DBField(DBConstants.sign.SHEET_ID)
long sheetId;
}
解釋:由于我們上面定義的DBField注解,使用是在成員變量使用,所以這里我們在ApplicantResult
類的屬性sheetId
中使用,我們發(fā)現(xiàn)為什么不是使用@DBField(value=DBConstants.sign.SHEET_ID)
呢?
這里使用注解的過程中有幾個隱晦的使用規(guī)則
- 如果注解中定義了value元素
- 如果在使用注解時value是惟一需要賦值的元素
- 那么只需在括號內(nèi)給出value的值即可
- 如果沒有給相應的注解賦值,那么將使用注解中的默認值,類似于@DBField(),value值默認被賦予空值(即default "")
所以這里才有了我們簡寫的注解使用
栗子2
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}
對于元注解@Target,如果你希望一個注解可以作用于ElementType中的所有類型,那么就可以不使用@Target——@Deprecated就是這樣做的。
注解的使用
注解的使用,主要是依據(jù)@Retention的分類,可以在源碼,編譯時,運行時,結(jié)合不同的@Target配合使用,我們下面主要講解一下注解有哪幾種使用場景
- 基于運行時反射方式使用
@Retention(RetentionPolicy.RUNTIME)
參考我的另外一篇文章ButterKnife使用和原理 - 基于APT的注解處理工具(Java Annotation Processing Tools)