JAVA技术补全——注解和反射

@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注解,它是一个元注解,用于指定数值的范围
解决方案如下

  1. 定义注解
@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 且会将注解擦除。因此相对于枚举来说资源消耗小。

你可能感兴趣的:(JAVA技术补全——注解和反射)