Java注解学习笔记(一)基本概念

  • 注解的概念
  • 注解的语法与定义形式
  • 单个注解举例分析
  • 注解的分类
  • 第一种分法根据注解如何创建的来定义
  • 第二种分法根据注解的生命周期来定义


注解的概念

       注解(Annotation),也叫元数据(Metadata),是Java5的新特性,JDK5引入了Metadata很容易的就能够调用Annotations。注解与类、接口、枚举在同一个层次,并可以应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中,用来对这些元素进行说明注释。

注解的语法与定义形式

  1. 以@interface关键字定义
  2. 注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
  3. 成员赋值是通过@Annotation(name=value)的形式。
  4. 注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。

单个注解举例分析

java.lang.annotation 中定义的 Target 注解来说明:
@Target: 定义注解的作用目标(作用域)

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

源码分析如下:
第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。
第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
第三:成员名称为value,类型为ElementType[]
另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:

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

@Target注解作用域枚举类:

@Target(ElementType.TYPE)
package java.lang.annotation;

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
}

分别为:

  • TYPE: 指的是在类,接口(包括注解)或者enum上使用的注解。
  • FIELD: 指的在field属性,也包括enum常量使用的注解。
  • METHOD: 指的是在方法声明上使用的注解。
  • PARAMETER: 指的是在参数上使用的注解。
  • CONSTRUCTOR: 指的是在构造器使用的注解。
  • LOCAL_VARIABLE: 指的是在局部变量上使用的注解。
  • ANNOTATION_TYPE: 指的是在注解上使用的元注解。
  • PACKAGE: 指的是在包上使用的注解。

注解的分类

       注解的分类有两种分法:

第一种分法根据注解如何创建的来定义

  • 基本内置注解,是指Java自带的几个Annotation,如@Override、Deprecated、@SuppressWarnings等;
  • 元注解(meta-annotation),是指负责注解其他注解的注解,JDK 1.5及以后版本定义了4个标准的元注解类型,如下:

@Target:标明注解的修饰目标,作用域取值范围可参考👆上面章节介绍章节内容

@Retention:指Annotation被保留的时间长短,标明注解的生命周期,通过RetentionPolicy取值有3种,如下:

  • SOURCE:在源文件中有效(即源文件保留)
  • CLASS:在class文件中有效(即class保留)
  • RUNTIME:在运行时有效(即运行时保留)

@Documented:标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化

@Inherited:标记注解,允许子类继承父类的注解

  1. 自定义注解,根据需要可以自定义注解,自定义注解需要用到上面的meta-annotation

第二种分法根据注解的生命周期来定义

  1. 源码时注解(RetentionPolicy.SOURCE)
  2. 编译时注解(RetentionPolicy.CLASS)
  3. 运行时注解(RetentionPolicy.RUNTIME)

       注解需要标明注解的生命周期,这些信息是通过元注解 @Retention 实现,注解的值是 enum 类型的 RetentionPolicy,包括以下几种情况

public enum RetentionPolicy {
    /**
     * 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃.
     * 这意味着:Annotation仅存在于编译器处理期间,编译器处理完之后,该Annotation就没用了
     */
    SOURCE,
 
    /**
     * 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期.
     */
    CLASS,
 
    /**
     * 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,
     * 保存到class对象中,可以通过反射来获取
     */
    RUNTIME
}