1.注解的意义
注解本身没有意义,它是作为一种标记或者注释存在。需要结合反射、插桩才有作用
jdk1.5引入,对于被注解的代码没有影响
2.元注解
是用于注解的注解:meta-annotation
Target:注解的使用范围
public enum ElementType {
TYPE, // 类、接口、枚举类
FIELD, // 成员变量(包括:枚举常量)
METHOD, // 成员方法
PARAMETER, // 方法参数
CONSTRUCTOR, // 构造方法
LOCAL_VARIABLE, // 局部变量
ANNOTATION_TYPE, // 注解类
PACKAGE, // 可用于修饰:包
TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
}
Retension:注解保留的时间范围
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 编译期保留,默认值
RUNTIME // 运行期保留,可通过反射去获取注解信息
}
Documented:用javac生成帮助文档时,是否保留注解信息
Inherited:被修饰的注解具有继承性
3.注解的使用场景
(1)source级别:编译器能获得注解和注解声明的类,能够获得其所有成员信息,一般用于编译器生成额外的代码,如APT技术
(2)class级别:编译出.class后,通过修改class数据实现修改代码逻辑的目的,如字节码增强、插桩等
(3)runtime级别:程序运行期间,通过反射动态获取注解和类信息,以完成修改,如反射
(4)Android语法检查,用@DrawableRes检查参数类型或@IntDef自定义入参类型检查
4.反射
典型反射代码应用:反射获取intent传值
public static void injectIntent2(Activity activity){
Class<? extends Activity> cls = activity.getClass();
Field[] fields = cls.getDeclaredFields();
for(Field field:fields){
if(field.isAnnotationPresent(InjectIntent.class)){
InjectIntent injectIntent = field.getAnnotation(InjectIntent.class);
String key = injectIntent.value();
Bundle bundle = activity.getIntent().getExtras();
field.setAccessible(true);
try {
field.set(activity,bundle.get(key));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}