@Target(ElementType.type)
@Retention(RetentionPolicy.SOURCE)
public @interface Anm {
}
元注解是指注解上的注解
Target 指定注解的作用域
- TYPE : 指定当前注解可以作用在class 、interface 、enum;
- FIELD :指定当前注解可以作用在参数上;
- METHOD :指定当前注解可以作用在方法上;
- PARAMETER :指定当前注解可以作用在参数上;
- CONSTRUCTOR:指定当前注解可以作用在构造函数上;
Retention 保留级别
- SOURCE: 注解会被保留在源码级别,会被编译器忽略
- CLASS :注解会被保留在字节码级别,会被编译器保留,但会被JVM忽略
-
RUNTIME: 注解会在运行时保留,由JVM保留,因此可以在运行时环境使用它
即: RUNTIME>CLASS>SOURCE
根据注解不同的保留级别,自然有不同的使用场景
级别 | 技术 | 说明 |
---|---|---|
SOURCE | APT | 在编译期间获取注解与注解声明的类包含的所有成员信息,一般用于生成辅助类相应的技术(JavaPoet) |
CLASS | 字节码增强 | 在编译出class后,通过修改class数据实现修改代码逻辑的目的。 |
RUNTIME | 反射 | 在程序运行期间,通过反射技术动态获取注解及其元素,从而完成不同的逻辑判断 |
注解使用场景1
public class AbsTest {
public static final int MON_DAY=0;
public static final int SUN_DAY=1;
@WekDay private int mWekDay;
public void setWekDay(int wekDay){
this.mWekDay=wekDay;
}
}
这种场景下我们期待使用者在调用setWekDay的时候传递MON_DAY或者SUN_DAY,但实际上传任何int值都不会报错,但是这并不是我们期望的。
这时我们的解决方案是:
private WekDays mDay;
public static enum WekDays{
MON_DAY,SUN_DAY;
}
public void setWekDay(WekDays wekDay){
this.mDay=wekDay;
}
这样做确实可以解决我们的问题,但我们就会多1个枚举类,并且相比于int类型来说枚举类占用的资源更大。
那么我们的解决方案就是采用注解的形式去解决这类问题,在androidx中sdk为我们提供了@IntDef注解,它是一个元注解,用于指定数值的范围
解决方案如下:
- 定义注解
@IntDef({AbsTest.MON_DAY,AbsTest.SUN_DAY})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD,ElementType.PARAMETER})
public @interface WekDay {
}
2.使用注解
//AbsTest.java
public static final int MON_DAY=0;
public static final int SUN_DAY=1;
@WekDay private int mWekDay;
public void setWekDay(@WekDay int wekDay){
this.mWekDay=wekDay;
}
这样在编译时编译器会检查wekDay是否合法。因为该注解的保留周期在源码级别。所以不会编译成class 且会将注解擦除。因此相对于枚举来说资源消耗小。
网友评论