Java高级

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

2020-11-05  本文已影响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)注解参数必须有确定的值。在定义的时候给默认值或在使用的时候指定参数值

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

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

上一篇 下一篇

猜你喜欢

热点阅读