Android定义了很多有用的注解,可供我们使用,方便编程减少潜在错误的发生。
1 @Override @ NonNull @Nullable
Android 中最常见的就是@Override,继承基类,重写函数时不加@Override不会报错,加上@Override编译期会帮我们检查重写是否合法,如果参数,或者类型的不合法会给警告。
@NonNull 告诉编译器,参数非空,可以避免函数内部参数null判断,也会避免很多错误。
@Nullable 告诉编译器 参数可以为null。
2 @ IntDef,@StringDef注解
@IntDef和@StringDef注解可以很好的对函数参数进行限定。
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE})
public @interface StringDef {
String[] value() default {};
}
如果一个类,有三个类型,通常的做法可以直接用String或者int常量标识,或者用Enum,或者用注解,String或int只能限定类型,无法阻止用户输入,Enum比较耗费内存,注解是个不错的选择。
例如:
public class Demo1 {
public static final String type1 = "type1";
public static final String type2 = "type2";
public static final String type3 = "type3";
enum TypeEnum {
TYPE1("type1"),
TYPE2("type2"),
TYPE3("type3");
private String type;
TypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@StringDef({type1, type2, type3})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@interface TypeAnn{ }
public void test2(String type){ }
public void test3(TypeEnum type){ }
public void test4(@TypeAnn String type){ }
public void test5(){
test2("sldjfls");
test3(TypeEnum.TYPE1);
test3("sdlfjs");
test4("sldjfs");
test4(type1);
}
@StringDef({"a1", "a2", "a3"})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@interface StringAnn{ }
public void test5(@StringAnn String name){
}
public void test6() {
test5("asldjfls");
test5("a1");
}
}
@IntDef 用法类似:
除了@IntDef和@StringDef注解类似的还有@LongDef,它们都只能用于注解
3 @IntRange,@LongRange
@Retention(SOURCE)
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
public @interface IntRange {
/** Smallest value, inclusive */
long from() default Long.MIN_VALUE;
/** Largest value, inclusive */
long to() default Long.MAX_VALUE;
}
从源码可以看到,IntRange可以应用的范围比较广,METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE。
可以应用于方法(返回值),方法参数,字段,局部变量,注解类型,用的比较多的还是方法的参数上,或者返回值上。
@Size
定义长度大小,例如函数参数的长度。
@Retention(SOURCE)
@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD})
public @interface Size {
/** An exact size (or -1 if not specified) */
long value() default -1;
/** A minimum size, inclusive */
long min() default Long.MIN_VALUE;
/** A maximum size, inclusive */
long max() default Long.MAX_VALUE;
/** The size must be a multiple of this factor */
long multiple() default 1;
}
4 资源类相关
@AnimatorRes,@AnimRes,@DimenRes,@DrawableRes,@FontRes,@IdRes,@InterpolatorRes,@LayoutRes,@MenuRes
@PluralsRes,@RawRes,@StringRes,@StyleableRes,@StyleRes,@TransitionRes,@XmlRes。
@ArrayRes,@BoolRes,@IntegerRes。
@ColorRes,@ColorLong,@ColorInt。
资源注解可以防止在使用资源时,传递错误资源类型。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="intid">22</integer>
<item name="intid2" type="integer">22</item>
<array name="array1">
<item > 11</item>
<item > 12</item>
<item > 13</item>
<item > 14</item>
</array>
<item name="string" type="string">sldjfsdfl</item>
<item name="id2" type="id"/>
</resources>
5 其他
@RequiresApi ,@RequiresFeature,@RequiresPermission,@RestrictTo,@UiThread,@VisibleForTesting,@WorkerThread,
@MainThread,@Keep,@GuardedBy,@CallSuper。
@RequiresApi 需要的api版本
@RequiresFeature 需要的feature,AndroidManifest.xml中设置
@RequiresPermission 需要的权限
@Keep 代码混淆,不混淆
@CallSuper注解主要是用来强调在覆盖父类方法的时候,需要实现父类的方法,及时调用对应的super.**方法
@RestrictTo 注解的对象只接受一个特定范围的值,值范围是一个枚举
@GuardedBy用来代替锁,表示某变量只能在线程持有锁时被某些线程访问
@UiThread,MainThread,WorkerThread标识类中方法在哪个 工作。