注解的基本使用

注解声明

java中所有的注解,默认实现Annotation接口,与class相比定义注解需要使用@interface关键字

    public @interface CAnnotation{
    }

元注解

定义:对注解类型进行注解的注解类(听着有点绕其实就是作用在注解上的注解)称之为meta-annotation(元注解)

一般在使用注解的时候用的两个注解@Taget 和@Retention 另外还有两个@Documented,@Inherited

  • @Taget
    注解另一个注解,限定可以应用注解的java元素类型.
    *ElementType.ANNOTATION_TYPE 应用与注解类型 限定注解
    *ElementType.CONSTRUCTOR 应用与构造函数
    *ElementType.FIELD 应用于字段或属性
    *ElementType.LOCAL_VARIABLE 应用于局部变量
    *ElementType.METHOD 应用于方法
    *ElementType.PACKAGE 应用于包声明
    *ElementType.PARAMETER 应用于方法参数
    *ElementType.TYPE 应用于类的任何元素

  • @Retention
    注解制指定注解的存储方式:
    *RetentionPolicy.SOURCE 标记的注解仅保留在源码级别中,被编译器忽略
    *RetentionPolicy.CLASS 标记的注解在编译时由编译器保留,但是java虚拟机JV会忽略
    *RetentionPolicy.RUNTIME 标记的注解由JVM保留,运行时还击可以使用它

@Rentention三个值中SOURCE<CLASS<RUNTIME

eg:


    @Target(Element.TYPE,Element.FIELD)//可以指定多个限定类型:允许在类与属性上标记
    @Rentention(RententionPolicy.SOURCE)//指定注解保留在源码级
    public @interface annotationC{
    String value();//无默认值
    int age() default 1;//有默认值
    }
    //使用
    @annotationC(value="v",age=0)
    class AAA{
    }

[注意] 如果定义注解参数时,仅有value参数,那么在使用注解时可以直接写值:@annotationC(“value”)

应用场景

通过以上内容可知Rentention元注解的存储方式有三种,那么逐一看一下:

  • SOURCE
    它是作用在源码级别,可以提供给IDE语法检查,APT等场景使用(后边在介绍)
    eg:
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RESOURCE)
public @interface TestAnnotation {
    int value();
    String id() ;
}
@TestAnnotation(value = 1,id="2")
public class Test {
}

jvm编译字节码显示

public class com/enjoy/annotation/Test {
// compiled from: Test.java
  // access flags 0x1
  public ()V
   L0
    LINENUMBER 4 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object. ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/enjoy/annotation/Test; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1
}

jvm忽略的注解信息在字节吗中并没有看到相关信息

  • 在开发中会应用到IDE 语法检查,suppor-annotations与androidx.annotation中均有提供@IntDef,@StringDef等注解此注解可以起到限定参数的作用
@IntDef(value = {Utils.MAN, Utils.WOMAN})
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Teacher {

    }
    public class Test {
        public static void main(String[] args) {
           //compare(1);//Must be one of: Utils.MAN, Utils.WOMAN 
             compare(Utils.MAN);
        }
        public static void compare(@Teacher int value){
            //do something
        }
    }

同样是传递int类型值,加了限定注解后,输入类型必须是指定类型否则报错,android中传递资源文件也是这样着的

APT注解处理器
APT全称"Annotation Processor Tools 意为注解处理器

编写好的java源文件-----javac------>虚拟机能够加载解析的字节吗CLASS文件,注解处理器是javac自带的一个工具,作用是编译时期扫描注解信息,我们注册自己的注解处理器,将注解信息传递给注解处理器处理

注解处理器是对注解应用最为广泛的场景。在Glide、EventBus3、Butterknifer、Tinker、ARouter等等常用
框架中都有注解处理器的身影。但是你可能会发现,这些框架中对注解的定义并不是 SOURCE 级别,更多的
是 CLASS 级别,别忘了:CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。

自定义注解处理器

@SupportedAnnotationTypes("com.enjoy.annotation.Teacher")//自己定义注解的全路径
        public class TeacherProcessor extends AbstractProcessor {
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        Messager messager = processingEnv.getMessager();
        messager.printMessage(Diagnostic.Kind.NOTE, "================================");
        //可以网络请求
        // 反射操作等等
        return false;
    }
}
  • ClASS
    定义为class的注解,会保留在class文件中,但是会被虚拟机jvm忽略(无法在运行期间反射获取注解).
    此时完全符合此种注解的应用场景是字节码操作,比如AspectJ,热修复Roubust;
    字节码操作是指直接修改字节码Class文件以达到修改代码执行逻辑的目的,比如在程序中多处需要进行是否登录判断

如果我们使用普通的编程方式,需要在代码中进行 if-else 的判断,如果判断点非常多,就需要在每个判断点加
入此项判断。此时,我们可以借助AOP(面向切面)编程思想,将程序中所有功能点划分为: 需要登录 与 无需登录
两种类型,即两个切面。对于切面的区分即可采用注解。


//Java源码
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.CLASS)
        public @interface Login {
        }
        
        @Login
        public void jumpA(){
        startActivity(new Intent(this,AActivity.class));
        }
        public void jumpB(){
        startActivity(new Intent(this,BActivity.class));
        }
  //字节码
          public void jumpA() {
          if (this.isLogin) {
          this.startActivity(new Intent(this, LoginActivity.class));
          } else {
          this.startActivity(new Intent(this, AActivity.class));
          }
          }
          public void jumpB() {
          startActivity(new Intent(this,BActivity.class));
          }

  • RUNTIME
    注解保留至运行期,我们能够在运行期间结合反射技术获取注解中的所有信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值