Android 開發中需要知道的註解
一、什麼是註解(Annotation)?
簡單的說就是元資料(Metadata),即一種描述資料的資料。所以說註解就是原始碼的元資料。更具體的就是一種應用於類、方法、引數、變數、構造器及包宣告中的特殊修飾符。它是一種由JSR-175標準選擇用來描述元資料的一種工具。JDK5中引入了Metadata很容易的就能夠呼叫註解。
二、為什麼引入註解?
在Annotation出現前,XML被廣泛的應用於描述元資料。在開發過程中一些應用開發人員和架構師發現XML的維護越來越糟糕。他們希望使用一些和程式碼緊耦合的東西,而不是像XML那樣和程式碼是鬆耦合的(在某些情況下甚至是完全分離的)程式碼描述,於是就出現了註解。目前,許多框架將XML和Annotation兩種方式結合使用,平衡兩者之間的利弊。
三、註解的語法與定義形式
- 以@interface關鍵字定義
- 註解包含成員,成員以無引數的方法的形式被宣告。其方法名和返回值定義了該成員的名字和型別。
- 成員賦值是通過@Annotation(name=value)的形式。
- 註解需要標明註解的生命週期,註解的修飾目標等資訊,這些資訊是通過元註解實現。
Java提供了四種元註解,專門負責新註解的建立工作,即註解其他註解。
@Target
定義了Annotation所修飾的物件範圍,Annotation可被用於 packages、types(類、介面、列舉、Annotation型別)、型別成員(方法、構造方法、成員變數、列舉值)、方法引數和本地變數(如迴圈變數、catch引數)。在Annotation型別的宣告中使用了target可更加明晰其修飾的目標。取值():ElementType.CONSTRUCTOR
:用於描述構造器ElementType.FIELD
:用於描述域ElementType.LOCAL_VARIABLE
:用於描述區域性變數ElementType.METHOD
:用於描述方法ElementType.PACKAGE
:用於描述包ElementType.PARAMETER
:用於描述引數ElementType.TYPE
:用於描述類、介面(包括註解型別) 或enum宣告ElementType. ANNOTATION_TYPE
:註解上使用的元註解
@Retention
定義了該Annotation被保留的時間長短:某些Annotation僅出現在原始碼中,而被編譯器丟棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛擬機器忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因為Annotation與class在使用上是被分離的)。取值:RetentionPoicy.SOURCE
:註解只保留在原始檔,當Java檔案編譯成class檔案的時候,註解被遺棄;用於做一些檢查性的操作,比如 @Override 和 @SuppressWarningsRetentionPoicy.CLASS
:註解被保留到class檔案,但jvm載入class檔案時候被遺棄,這是預設的生命週期;用於在編譯時進行一些預處理操作,比如生成一些輔助程式碼(如 ButterKnife)RetentionPoicy.RUNTIME
:註解不僅被儲存到class檔案中,jvm載入class檔案之後,仍然存在;用於在執行時去動態獲取註解資訊。
@Documented
標記註解,用於描述其它型別的註解應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文件化,不用賦值。- @Inherited
標記註解,允許子類繼承父類的註解。
上面的理論可能不太直觀,下面以與註解Target
舉例說明一下:
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.ANNOTATION_TYPE } )
public @interface Target {
ElementType[] value();
}
1:元註解@Retention
,成員value的值為RetentionPolicy.RUNTIME
。
2:元註解@Target
,成員value是個陣列,用{}形式賦值,值為ElementType.ANNOTATION_TYPE
3:成員名稱為value
,型別為ElementType[]
!注意:如果成員名稱是value,在賦值過程中可以簡寫。如果成員型別為陣列,但是隻賦值一個元素,則也可以簡寫。如上面的簡寫形式為:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
框架中常見註解
- JDK內建的其他註解
@Override、@Deprecated、@SuppressWarnings、@SafeVarargs、@FunctionalInterface、@Resources等。
- Android SDK內建的註解
- 資源引用限制類:用於限制引數必須為對應的資源型別
@AnimRes @AnyRes @ArrayRes @AttrRes @BoolRes @ColorRes
等 - 執行緒執行限制類:用於限制方法或者類必須在指定的執行緒執行
@AnyThread @BinderThread @MainThread @UiThread @WorkerThread
- 引數為空性限制類:用於限制引數是否可以為空
@NonNull @Nullable
- 類型範圍限制類:用於限制標註值的值範圍
@FloatRang @IntRange
- 型別定義類:用於限制定義的註解的取值集合
@IntDef @StringDef
- 資源引用限制類:用於限制引數必須為對應的資源型別
Android SDK 內建的註解都在包com.android.support:support-annotations
裡,具體的使用介紹見官方文件:傳送門
Java註解的思維導圖
最後引用網上大神的一張思維導圖如下: