本文出自 “一剑围城” 博客,原地址http://weijiancheng.blog.51cto.com/10190955/1945266
在使用许多第三方框架的时候,查阅源码如ButterKnife等。发现许多注解的使用,顿时觉得注解都玩不溜怎么称霸武林。当然无论Java还是Android的SDK中都有大量注解的使用,以前总是走马观花,印象中知道注解代表的意思,但开口总是说不清道不明,唯有总结方得始终。
注解是附加在代码中的一些信息,可以帮助一些代码分析工具如Lint分析代码,辅助开发者改善代码,对于开发者来说有个提示、警告的作用。但注解不会改变代码逻辑。在此总结了几个Android开发常见的注解的解释,以及对元注解的基本认识。
常见的几个注解
1、@TargetApi
2、@RequiresApi
3、@suppressLint
4、@SuppressWarnings
@TargetApi(Build.VERSION_CODES.M)、@TargetApi(23)
Lint会按照API版本M以上扫描代码,而不是project中指定的minSDKVersion,可以使得高版本Api在低版本SDK上Lint不报错。如果只加这个注解,表明这段代码只能在23及以上的系统上运行,如果你非要在23以下的系统上运行,那该警告的已经警告了,你只是忽略了警告,但运行时该错还是错。
@RequiresApi(api = Build.VERSION_CODES.M)
表示注解目标只能够在指定的版本API及以上运行,消除高版本Api在低版本SDK上的报错,作用上和TargetApi相同,只是在词面上更清楚表达了这是一个建议,而不仅仅是为了消除高版本Api在低版本SDK上的报错。从官方的表述可以看出更推荐使用RequiresApi替换TargetApi。
@SuppressLint("NewApi")
最直接暴力屏蔽指定名称的报错,这里的NewApi对应的具体错误名称是:Calling new methods on older versions。这里的NewApi只是一个缩写名称。相比于@TargetApi指定了版本号,SuppressLint是一律屏蔽,所以一般不建议使用。当然还可以指定任何其他Lint定义好的错误名称。在settings中查找Inspections可以找到预先定义好的所有Error、Warning。对于多个错误,使用逗号隔开。
在XML中类似的做法有:
tools:ignore="ScrollViewCount,UselessParent"忽略XML中的两个警告。
@SuppressWarnings("NumericOverflow")
屏蔽NumericOverflow警告,如:int a = 1 / 0;
一般的语句注解方式suppress for statement
@SuppressWarnings("NumericOverflow")
int a = 10 / 0;
注释注解方式statement for statement with comment
//noinspection NumericOverflow(以前总是看到这样的注释,但并不知道也是注解)
int a = 10 / 0;
当然,这些注解可以使用在许多地方如:class、method、statement,分别对应由大到小不同的作用域类、方法、语句,当然作用域范围越大,那么性能损耗自然越大。
Annotation不影响代码逻辑
这些注解的作用只是去除Lint的错误警告,并不能影响任何的代码逻辑。
所以必须在代码中添加相应的兼容性判断代码,如:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
color = getColor(R.color.colorAccent);
}
当然,当你添加完上述兼容代码后,警告也就消失了。
元注解(注解的注解)
常见的元注解:
1、@Documented
2、@Inherited
3、@Retention
4、@Target
分析SuppressLint的定义:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.CLASS)
public @interface SuppressLint {
value();
}
@Target定义作用目标
其中@Target指定了SuppressLint的作用目标,具体TYPE、FIELD等代表什么,可以在java.lang.annotation.ElementType里面找到。
例如:TYPE表示
/** Class, interface (including annotation type), or enum declaration */
即包含了类、接口(包括注解)、枚举类型。
例如:@Override注解
@Target(ElementType.METHOD) 重写,只能作用于方法
@Retention(RetentionPolicy.SOURCE) 只存在于编码阶段,编译阶段就失效了
public @interface Override {}
@Retention定义保留策略
1、PetentionPolicy.SOURCE 仅保留在源码阶段,编译阶段就失效
2、PetentionPolicy.CLASS默认策略,会保留到编译出字节码阶段,运行时失效
3、PetentionPolicy.RUNTIME 保留到VM的运行时阶段,可通过反射获得
@Documented 注解将被写入javadoc中
@Inherited 子类可以继承父类中的该注解
@Repeatable 找不到例子,有待理解
@Native 尚处于Preview状态,表示常量有可能被本地代码引用