java annotation 詳解

在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ī)則

  1. 如果注解中定義了value元素
  2. 如果在使用注解時value是惟一需要賦值的元素
  3. 那么只需在括號內(nèi)給出value的值即可
  4. 如果沒有給相應的注解賦值,那么將使用注解中的默認值,類似于@DBField(),value值默認被賦予空值(即default "")

所以這里才有了我們簡寫的注解使用

栗子2

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}

對于元注解@Target,如果你希望一個注解可以作用于ElementType中的所有類型,那么就可以不使用@Target——@Deprecated就是這樣做的。

注解的使用

注解的使用,主要是依據(jù)@Retention的分類,可以在源碼,編譯時,運行時,結(jié)合不同的@Target配合使用,我們下面主要講解一下注解有哪幾種使用場景

  1. 基于運行時反射方式使用
    @Retention(RetentionPolicy.RUNTIME)
    參考我的另外一篇文章ButterKnife使用和原理
  2. 基于APT的注解處理工具(Java Annotation Processing Tools)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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