美文网首页Java高级
Java---Annotation之旅(初识篇)

Java---Annotation之旅(初识篇)

作者: 初夏的雪 | 来源:发表于2020-11-05 10:11 被阅读0次

    1、Annotation 概念

    ​ Annotation 注解,标注。(JDK 1.5 引入的一种注释机制)。

    通俗理解:

    ​ 注解就是一种通过在类、方法或者属性等上使用类似@XXX的方式进行打标签,然后再通过一些手段对标签进行解析和处理的技术手段。说白了就是一种特殊的标签。

    Java 内置了10 个注解 :

    作用在代码上的注解(3个),在 java.lang 包下,分别是:@Overide(方法重载)、@Deprecated(过时、弃用)、@SuppressWarnings(忽略警告)

    作用在注解上的注解 ( 即 元注解 ) 4个,在 java.lang.annotation 包下,分别是:@Target (目标)、@Retention(保留期) 、@Documented(文档)、@Inherited(继承)

    Java 7 之后新增加的注解 (3个) : 在 java.lang 包下,分别是:@FunctionalInterface (函数接口)、@SafeVarargs(安全)

    在 java.lang.annotation 包下, @Repeatable (重复声明)

    接下来我们从思维导图和源码来系统的认识一下Annotation:

    Annotation体系框架图.png

    1.1 作用在代码上的注解:

    1.1.1 @Override: 标识该方法是重写父类的方法

    /**
    *Indicates that a method declaration is intended to override a method declaration in a supertype.
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }
    

    1.1.2 @Deprecated: 标识该方法或者类已经被弃用,建议不要使用

    /**
    *A program element annotated @Deprecated is one that programmers are discouraged from using, typically because it is dangerous,or *because a better alternative exists.  
    */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    

    1.1.3 @SuppressWarnings: 指示编译器去忽略注解中声明的警告

    /**
     * Indicates that the named compiler warnings should be suppressed in the
     * annotated element (and in all program elements contained in the annotated
     * element). 
     */
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }
    
    

    1.2 作用在注解上的注解(元注解)

    1.2.1@Target: 用于标记该注解会被用在什么地方。

    /**
    *  Where Annotations My Appear
    */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
        /**
         * Returns an array of the kinds of elements an annotation type
         * can be applied to.
         * @return an array of the kinds of elements an annotation type
         * can be applied to
         */
        ElementType[] value();
    }
    
    public enum ElementType {
        /** Class, interface (including annotation type), or enum declaration */
        TYPE,
        
        /** Field declaration (includes enum constants) */
        FIELD,
    
        /** Method declaration */
        METHOD,
    
        /** Formal parameter declaration */
        PARAMETER,
    
        /** Constructor declaration */
        CONSTRUCTOR,
    
        /** Local variable declaration */
        LOCAL_VARIABLE,
    
        /** Annotation type declaration */
        ANNOTATION_TYPE,
    
        /** Package declaration */
        PACKAGE,
    
        /**
         * Type parameter declaration
         * @since 1.8
         */
        TYPE_PARAMETER,
    
        /**
         * Use of a type
         * @since 1.8
         */
        TYPE_USE
    }
    

    1.2.2 @ Retention 标记这个注解的"寿命".

    有三种:SOURCE--代码中,,编译器会忽略、 CLASS---class 文件中,JVM会忽略、 RUNTIME---运行时

    CLASS 包含了 SOURCE ,RUNTIME 包含了CLASS ,SOURCE

    /**
     * Indicates how long annotations with the annotated type are to
     * be retained.  If no Retention annotation is present on
     * an annotation type declaration, the retention policy defaults to
     * {@code RetentionPolicy.CLASS}.
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
        /**
         * Returns the retention policy.
         * @return the retention policy
         */
        RetentionPolicy value();
    }
    
    /**
    *  retention的属性值
    */
    public enum RetentionPolicy {
        /**
         * Annotations are to be discarded by the compiler.
         */
        SOURCE
        /**
         * Annotations are to be recorded in the class file by the compiler
         * but need not be retained by the VM at run time.  This is the default
         * behavior.
         */
        CLASS,
    
        /**
         * Annotations are to be recorded in the class file by the compiler and
         * retained by the VM at run time, so they may be read reflectively.
         *
         * @see java.lang.reflect.AnnotatedElement
         */
        RUNTIME
    }
    
    

    1.2.3 @Documented 标记注解包含在用户文档中

    /**
     * Indicates that annotations with a type are to be documented by javadoc
     * and similar tools by default.  This type should be used to annotate the
     * declarations of types whose annotations affect the use of annotated
     * elements by their clients.  If a type declaration is annotated with
     * Documented, its annotations become part of the public API
     * of the annotated elements.
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Documented {
    }
    
    

    1.2.4 @Inherited 允许子类继承父类中的注解

    /**
     * Indicates that an annotation type is automatically inherited.  If
     * an Inherited meta-annotation is present on an annotation type
     * declaration, and the user queries the annotation type on a class
     * declaration, and the class declaration has no annotation for this type,
     * then the class's superclass will automatically be queried for the
     * annotation type. 
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Inherited {
    }
    

    1.3 新增的注解

    1.3.1 @SafeVarargs 忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告

    /**
     * A programmer assertion that the body of the annotated method or
     * constructor does not perform potentially unsafe operations on its
     * varargs parameter.  
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
    public @interface SafeVarargs {}
    
    

    1.3.2 @FunctionalInterface 标识一个匿名函数或函数式接口

    /**
     * An informative annotation type used to indicate that an interface
     * type declaration is intended to be a <i>functional interface</i> as
     * defined by the Java Language Specification.
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FunctionalInterface {}
    
    

    1.3.3 @Repeatable 标识某注解可以在同一个声明上使用多次

    /**
     * The annotation type {@code java.lang.annotation.Repeatable} is
     * used to indicate that the annotation type whose declaration it
     * (meta-)annotates is <em>repeatable</em>. The value of
     * {@code @Repeatable} indicates the <em>containing annotation
     * type</em> for the repeatable annotation type.
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Repeatable {
        /**
         * Indicates the <em>containing annotation type</em> for the
         * repeatable annotation type.
         * @return the containing annotation type
         */
        Class<? extends Annotation> value();
    }
    
    

    2.Annotation 对应关系

    Annotation 关系对应图

    ​ 从上面架构图可以看出:

    1. 一个Annotation 和 一个RetentionPolicy 关联,即每一个Annotation对象有且只有一个RetentionPolicy属性。

    2. 一个Annotation 和 1~n个ElementType 关联,即每一个Annotation对象可以用 大于等于 1个的ElementType属性。

    3. 因为Annotation是一个接口,那么他的实现类,全部都满足1,2 两条的关联关系。

    3.Annotation 使用场景

    ​ Annotation 是一个辅助类,我们经常使用到的有:

    1. 如果RetentionPolicy == SOURCE时,为编译器进行编译语法检查,APT等场景
    2. RetentionPolicy == CLASS时,会保留在class文件中,会被虚拟机忽略。此时完全符合的场景是字节码操作:AspectJ 、热修复Roubust等;
    3. 如果RetentionPolicy == RUNTIME 时,则我们可以在反射中解析并使用;
    4. 如果使用@Documented注解,可以使该注解出现在javadoc中,生成帮助文档
    5. 通过注解方便了解代码结构

    ​ 知识点:

    ​ 1)APT (Annotation Processor Tools) ,注解处理器,用于处理注解。编写好的java源文件,经过javac编译后翻译为虚拟机能够加载解析的字节码Class 文件。注解处理器用来在编译时期扫描处理注解信息。你可以为某些注解注册自己的注解处理器,此注解处理器由javaC调起,并将注解信息传递给注解处理器进行处理。更多关于注解处理器在后续的文章中详细介绍。

    ​ 2)所谓字节码操作,就是直接修改字节码Class文件以达到修改代码执行逻辑的目的。

    4.Annotation 自定义

    下面我们来简单的自定义个Annotation:

    package com.leon.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Documented
    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.FIELD)
    public @interface BindView {
        int viewId();
    }
    

    说明:

    1)注解是使用@interface 来定义的,其实和接口很像,但是@是必须的

    2)接口的参数定义如:int viewId (); 和类的成员变量类似,但是必须要带上圆括号“()”

    3)如果要给参数设置默认值,则直接在圆括号之后,f分号之前 加上 default XXX。 如: int viewId() default 0;

    4)@Target 注解里面可以有多个值(参考第二点的对应关系),如:@Target({ElementType.FIELD,ElementType.LOCAL_VARIABLE})

    5)如果注解只有一个参数,最好取名value ,这样可以在使用的时候注解指定属性值

    6)只能使用public和默认权限修饰符来修饰参数

    7)注解参数必须有确定的值。在定义的时候给默认值或在使用的时候指定参数值

    注解如果没有注解处理器来解析他,那么注解也没什么作用,那我们该怎么使用注解来完成一些工作呢? 杰西莱的文章中介绍。

    今天就到此结束了,欢迎各位留言评论。

    相关文章

      网友评论

        本文标题:Java---Annotation之旅(初识篇)

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