注解与反射

77 阅读1分钟

注解的作用

注解本身没有任何意义,单独的注解就是一种注释,他需要结合反射、插桩等技术才有意义。

定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {
    String value() default "";
}

//不设置任何数值
@Test()
public class Sample {
}

//设置其他数值,但是可以省略 value
@Test("lee")
public class Sample {
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {
    String name() default "";
}

//不能省略 name
@Test(name = "lee")
public class Sample {
}

//多个元素
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {
    String value();
    String name() default "";
}

@Test(value = "",name = "lee")
public class Sample {
}

不指定 Target 可以作用在任何地方

value 指定默认值,使用注解时可以不设置数值。

如果未指定默认值,必须设置数值。

value 是特殊的元素名字,可以省略 value,如果是其它名称,必须以 key-value 的形式

注解的使用场景

源码

APT,在编译期能够获取注解与注解声明的类包括类中所有成员信息,一般用于生成额外的辅助类。 javac采集所有的注解信息 -> Element -> 注解处理程序

代码检查

IDE 插件负责检查

@IntDef({0,1,2,3,4,5,6})
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.SOURCE)
public @interface WeekDay {
}

//限定 setWeekDay 方法 和 day 属性的范围是0~6
@WeekDay int day;
void setWeekDay(@WeekDay  int day){
    this.day = day;
}

字节码

字节码增强,在编译出 Class 后,通过修改 Class 数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解。

反射

在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。例如 gson 中的 TypeToken