【重学Java】(二)注解与反射

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();
                }
            }
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章