• android 注解详解


    1,注解的概念

    注解现在广泛的应用于android的各个开源框架中,不理解注解,我们就无法更好的提升我们的架构能力。那么什么是注解呢?注解(Annotation),是JDK5.0 引入的一种注释机制。 注解是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。

    2,注解的定义

    在java中,所有的注解都默认实现Annotation接口,接口如下:

    1. public interface Annotation {
    2. boolean equals(Object var1);
    3. int hashCode();
    4. String toString();
    5. Classextends Annotation> annotationType();
    6. }

    要定义一个注解,和定义一个接口差不多,只不过在interface前面多了一个@

    1. public @interface YuanZhen{
    2. }

    3,元注解

    在定义注解时,注解类也能够使用其他的注解声明。对注解类型进行注解的注解类,我们称之为 meta-annotation(元注解)

    元注解有四种类型:

    @Target指定注解的作用范围
    @Retention指定注解的作用时机
    @Inherited被该注解修饰的注解,作用在某个类上,该类的此注解可以被子类继承
    @Documented给Javadoc配置的
    @IntDefandroid新引入的,int类型,代替枚举的使用
    @StringDefandroid新引入的,String类型,代替枚举的使用

    最常用的是@Target 和@Retention。@Inherited和@Documented 一般很少用到,@IntDef和@StringDef多用来代替枚举,因为枚举的使用会增加内存的消耗。

    3.1 @Target

    @Target用来指定注解的作用范围,参数如下:

    ElementType.ANNOTATION_TYPE
    可以应用于注解类型
    ElementType.CONSTRUCTOR
    可以应用于构造函数
    ElementType.FIELD
    可以应用于字段或属性
    ElementType.LOCAL_VARIABLE
    可以应用于局部变量
    ElementType.METHOD
    可以应用于方法级注解
    ElementType.PACKAGE
    可以应用于包声明
    ElementType.PARAMETER
    可以应用于方法的参数
    ElementType.TYPE
    可以应用于类的任何元素

    可以看一下下面的例子:

    定义一个作用于方法参数的注解

    1. @Target(ElementType.PARAMETER)//作用于方法的参数
    2. public @interface YuanZhen {
    3. }

    当作用于类上时,就会报错,而作用于方法参数上,就可以正常运行

    3.2@Retention

    此元注解用来指定注解的作用时机,也就是说注解是在什么阶段有效,参数如下:

    RetentionPolicy.SOURCE
    标记的注解仅保留在源级别中,并被编译器忽略
    RetentionPolicy.CLASS
    标记的注解在编译时由编译器保留,但 Java 虚拟机 (JVM) 会忽略
    RetentionPolicy.RUNTIME
    标记的注解由 JVM 保留,因此运行时环境可以使用它
    3.2.1RetentionPolicy.SOURCE

    源码级别,在编译期能够获取注解与注解声明的类包括类中所有成员信息,一般用于生成额外的辅助类。

    这个最常用的技术就是APT技术,好多开源框架都是使用的这种技术,例如:ButterKnife,EventBus,ARout,IOC,ROOM等等,应用非常广泛,APT技术一般是结合JavaPoet使用,具体怎么使用,请参照android注解之APT和javapoet_袁震的博客-CSDN博客

    3.2.2RetentionPolicy.CLASS

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

    这个最常用的技术就是字节码插桩,字节码插桩框架主要有三种,ASM,Javassist,AspectJ。

    性能方面ASM最优。稳定性和简单性方面AspectJ最优。利用AOP思想,我们可以无侵入的实现埋点,监控方法耗时,UI卡顿监控,自动添加日志,代码隔离等等功能。以后有时间会讲解各个功能的实现方案。

    3.2.3 RetentionPolicy.RUNTIME

    上面两个都属于编译阶段,RetentionPolicy.RUNTIME属于运行时期,它是在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。

    这个最典型的使用案例就是反射,关于反射相信大家都不陌生了。如果有不清楚反射的,可以看一下android反射详解_袁震的博客-CSDN博客

    3.3@Inherited

    该注解的作用是子类可以继承父类的注解,意思就是,如果一个注解添加了@Inherited,例如:

    1. @Inherited
    2. @Target(ElementType.TYPE)
    3. public @interface YuanZhen {
    4. }

    那么用该注解修饰的类,其子类可以获取到该注解。

    3.4@IntDef 和@StringDef

    @IntDef 和@StringDef是安卓引入的新的元注解,这两个注解的主要作用是用来替代枚举的,因为枚举对内存的消耗比较大,下面来看怎么使用:

    自定义一个注解:

    1. @Inherited
    2. @Target(ElementType.PARAMETER)
    3. @Retention(RetentionPolicy.SOURCE)
    4. @IntDef({DataBean.DOCTOR, DataBean.TEACHER})
    5. public @interface YuanZhen {
    6. }

    数据类:

    1. public class DataBean {
    2. public static final int DOCTOR = 0;
    3. public static final int TEACHER = 1;
    4. private int type;
    5. public void setType(@YuanZhen int type) {
    6. this.type = type;
    7. }
    8. public int getType() {
    9. return type;
    10. }
    11. }

    使用时:

    @StringDef和@IntDef的用法一样,这里就不再举例了。

    4,注解类型元素

    注解允许我们在使用时传递参数,可以传递一个参数或者多个参数

    当只有一个参数需要传递时,我们可以这样写:

    1. @Inherited
    2. @Target(ElementType.METHOD)
    3. @Retention(RetentionPolicy.SOURCE)
    4. public @interface YuanZhen {
    5. String value() default "111";
    6. }
    1. @YuanZhen("222")
    2. public void testMethod(){
    3. }
    4. //因为有默认值 也可以这样写
    5. @YuanZhen()
    6. public void testMethod(){
    7. }
    注意:在使用注解时,如果定义的注解中的类型元素无默认值,则必须进行传值。
    当有多个参数时,可以这样写:
    1. @Inherited
    2. @Target(ElementType.METHOD)
    3. @Retention(RetentionPolicy.SOURCE)
    4. public @interface YuanZhen {
    5. String value() default "111";
    6. int age();
    7. }
    1. @YuanZhen(value = "222",age = 88)
    2. public void testMethod(){
    3. }

    5,总结

    关于注解的基本知识就是这些,基本的注解并不难掌握,但是后面想要提高自己的架构能力,就必须结合APT,JavaPoet以及字节码插桩技术和反射,综合运用到框架中去,这并不是一件简单的事情,但是了解之后,我们就会发现一片新的天地。

  • 相关阅读:
    【【萌新的FPGA学习之按键控制LED实验】】
    ipython一些使用方法
    与机器学习相比,人类的学习包括视觉、听觉、触觉、嗅觉、味觉的串并行混合学习...
    Allegro Design Entry HDL(OrCAD Capture HDL)视图管理菜单详细介绍
    Java函数式编程:三、流与函数式编程
    diskgenius数据恢复软件,亲测可用!
    logging日志改造---自定义参数传递到格式中
    SpringBean(配置、实例化、作用域、生命周期、装配方式)
    线性代数学习笔记8-3:二次型、合同矩阵、标准型、规范型
    基于SSM框架的电影院售票网站
  • 原文地址:https://blog.csdn.net/y2653904/article/details/132732880