在Java中,註解(Annotation)引入始於Java5,用來描述Java代碼的元信息,一般狀況下註解不會直接影響代碼的執行,儘管有些註解能夠用來作到影響代碼執行。html
在代碼文件中使用‘@’字符告訴編譯器接下來的是一個註解。註解能夠用在類,構造方法,成員變量,方法,參數等的聲明中。做用主要是對編譯器警告等輔助工具產生影響,若是傳遞了錯誤的類型那麼編譯器就會發出警告,這樣就能夠在編碼和維護的過程當中輔助發現問題,提升開發效率,提高代碼質量,也促進造成編碼規範。java
安卓開發中用到的註解主要有四個方面:JDK內置註解、JDK自定義註解包、android sdk內置註解、android.support.annotation註解。android
以下圖,左側是JDK提供的三個標準註解,在java.lang包內。右側JDK提供的四個是對自定義註解的支持,在java.lang.annotation包內。數組
@Deprecated是一個標記註解,表示被標記的成員變量或者成員方法已經不建議使用,緣由多是這個方法/變量有缺陷或者在新的SDK中已經不被支持。app
@Override註解在繼承過程當中,標識對父類方法的覆蓋關係。這個在Java中不是必須的,可是建議在須要的地方強制使用。防止在子類或者父類中誤操做修改方法簽名或者遺漏相關的代碼(kotlin中對於子類覆蓋父類方法強制使用override關鍵字,再也不須要註解標記)。ide
@SuppressWarnings用來抑制編譯器生成警告信息,對指定類型的警告保持靜默。能夠修飾類、方法、方法參數、屬性和局部變量,採用就近原則,儘可能放在被須要靜默的警告語句附近。接收一個字符串或者一個字符集做爲參數(參數詳細介紹參考文章),它指示將取消的警告。工具
JDK提供了四種元註解,支持用戶對註解進行自定義擴展。自定義註解後面會詳細介紹,這裏先略過。gradle
Android SDK註解有兩個@SuppressLint和@TargetApi。ui
@TargetApi:Android工程須要設置所支持的最小的系統版本,Android Studio是在Gradle中設置minSdkVersion的值。若是某個方法或者類被聲明須要在某個版本和更高版本的系統上運行,可使用@RequiresApi(requires)聲明支持的最小系統版本。當在聲明minSdkVersion的工程中使用了requires大於minSdkVersion的類或者方法時,Lint就會報錯誤提醒,這時候可使用@TargetApi使Lint保持靜默,可是要添加代碼爲低版本的系統提供對應的備選方案,不然在低版本系統上運行會產生崩潰。google
@SuppressLint:上面的@TargetApi註解只針對API版本進行註解,使Lint對版本錯誤保持靜默。@SuppressLint針對的範圍更廣,經過設置一個參數(identified by the lint issue id)通知Lint對相應的警告⚠和錯誤❎️保持靜默。
@SuppressLint("NewApi"),這個註解能夠實現@TargetApi(version)相同的做用,只是沒有指定特定的API版本,致使工程師和Lint都不知道響應的範圍,容易致使錯誤,不建議使用。
Android Support Library提供com.android.support:support-annotations對Android的註解進行了拓展。下圖以v25爲例列出了全部定義的46個註解(到v27增長了5個,分別爲ColorLong、FontRes、GuardedBy、HalfFloat、NavigationRes)。
枚舉類型的註解的使用,先定義一系列可用的取值,而後定義一個註解使用@IntDef或者@StringDef指定新的註解可用的取值列表。
使用 Enum 的缺點:每個枚舉值都是一個對象,在使用它時會增長額外的內存消耗,因此枚舉相比於Integer和String會佔用更多的內存,較多的使用 Enum 會增長 DEX 文件的大小,會形成運行時更多的開銷,使咱們的應用須要更多的空間。特別是分dex的大APP,枚舉的初始化很容易致使ANR。
@Retention(SOURCE)
@StringDef({
POWER_SERVICE,
WINDOW_SERVICE,
LAYOUT_INFLATER_SERVICE
})
public @interface ServiceName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
複製代碼
@Retention(SOURCE)
@IntDef({
NAVIGATION_MODE_STANDARD,
NAVIGATION_MODE_LIST,
NAVIGATION_MODE_TABS
})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();
複製代碼
上面的枚舉註解,就是自定義註解的例子。自定義註解使用關鍵字@interface聲明,而後用相應的屬性修飾。
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Entity {
String value();
String name();
}
複製代碼
implementation 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
複製代碼
在library工程中,直接使用R.xxx.xxx會報「元素值必須爲常量表達式」的錯誤提示,處理步驟以下:
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
複製代碼
apply plugin: 'com.jakewharton.butterknife'
複製代碼