美文网首页
Java注解

Java注解

作者: Android_Gleam | 来源:发表于2020-09-25 21:35 被阅读0次

    1.注解是什么,有什么意义

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

    Java 注解(Annotation)又称 Java 标注,是 JDK1.5 引入的一种注释机制。是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。

    2.注解的定义

    注解的定义很简单,我们直接使用@interface关键字就可以定义一个注解。
    public @interface Test {}
    这只是注解的简单定义,这么写是没有任何意义的,我们还需要加入其它的配置才可以。我们往下看。

    3.元注解

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

    @Target

    注解标记另一个注解,以限制可以应用注解的 Java 元素类型。目标注解指定以下元素类型之一作为其值:

    • @Target(ElementType.TYPE) 作用接口、类、枚举、注解
    • @Target(ElementType.FIELD) 作用属性字段、枚举的常量
    • @Target(ElementType.METHOD) 作用方法
    • @Target(ElementType.PARAMETER) 作用方法参数
    • @Target(ElementType.CONSTRUCTOR) 作用构造函数
    • @Target(ElementType.LOCAL_VARIABLE)作用局部变量
    • @Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)
    • @Target(ElementType.PACKAGE) 作用于包
    • @Target(ElementType.TYPE_PARAMETER) 作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)
    • @Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class (jdk1.8加入)

    下面我们看下Target的源码

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
        ElementType[] value();
    }
    

    由上面的源码可知Target可以指定多个,因为它的值是数组

    @Retention

    注解指定标记注解的存储方式:

    • @Retention(RetentionPolicy.SOURCE),标记的注解仅保留在源级别中,并被编译器忽略。
    • @Retention(RetentionPolicy.CLASS), 标记的注解在编译时由编译器保留,但 Java 虚拟机(JVM)会忽略。
    • @Retention(RetentionPolicy.RUNTIME), 标记的注解由 JVM 保留,因此运行时环境可以使用它。
    使用场景
    • RetentionPolicy.SOURCE:在编译期能够获取注解与注解声明的类包括类中所有成员信息,一般用于生成额外的辅助类。典型的代表,APT(Annotation Processor Tools 注解处理工具) 。

    注解处理器运行在编译阶段:java文件经过javac编译成.class文件,
    javac采集到所有的注解信息,包装成一个节点(Element),再由javac调用指定的注解处理程序。javac编译java文件的时候会调用注解处理器,然后在编译为class文件。所以注解处理器使用源码级别的注解就可以了。
    还有就是编译器代码检查,例如IntDef、@DrawableRes,语法检查是由ide或者ide插件实现的。

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

    • Retention(RetentionPolicy.RUNTIME)
      在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。

    @Inherited

    一个被@Inherited注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。

    /**
     * 自定义注解
     */
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyTestAnnotation {
    }
    
    /**
     * 父类标注自定义注解
     */
    @MyTestAnnotation
    public class Father {}
    
    //子类
    class Son extends Father{}
    
    public static void main(String[] args) {
            //获取Son的class对象
            Class<Son> sonClass = Son.class;
            // 获取Son类上的注解MyTestAnnotation可以执行成功
            boolean annotation = sonClass.isAnnotationPresent(MyTestAnnotation.class);
            //打印值为true
            System.out.println(annotation);
    }
    

    @ Repeatable

    被这个元注解修饰的注解可以同时作用一个对象多次

    //Persons
    @Target(ElementType.TYPE)  
    @Retention(RetentionPolicy.RUNTIME)
    public   @interface Persons {
        Person[] value();
    }
    
    //Person注解
    @Repeatable(Persons.class)
    public  @interface Person{
        String role() default "";
    }
    
    
    @Person(role="shuaige")
    @Person(role="shuaibi")
    @Person(role="dashuaige")
    @Person(role="dashuaibi")
    public  class ShuaiGe {
        String name="";
    }
    
    public static void main(String[] args) {
            if (ShuaiGe.class.isAnnotationPresent(Persons.class)) {
                Persons p2 = Man.class.getAnnotation(Persons.class);
                for (Person t : p2.value()) {
                    System.out.println(t.role());
                }
            }
    }
    

    @Documented

    用于被javadoc工具提取成文档。

    4.注解类型元素

    在上文元注解中,允许在使用注解时传递参数。我们也能让自定义注解的主体包含 annotation type element (注解 类型元素) 声明,它们看起来很像方法,可以定义可选的默认值。

    @Target({ElementType.TYPE,ElementType.FIELD}) 
    @Retention(RetentionPolicy.SOURCE) 
    public @interface ShuaiGe { 
        String value(); //无默认值 
        int age() default 1; //有默认值 
    }
    

    注意:在使用注解时,如果定义的注解中的类型元素无默认值,则必须进行传值。

    @Lance("帅") //如果只存在value元素需要传值的情况,则可以省略:元素名= 
    @Lance(value="帅",age = 2)
    int i;
    

    相关文章

      网友评论

          本文标题:Java注解

          本文链接:https://www.haomeiwen.com/subject/oyfwsktx.html