在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'
复制代码