Java注解(Annotation)


概念

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

内置的注解

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码的注解是

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

作用在其他注解的注解(或者说 元注解)是:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:

  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

Annotation架构图

我们可以从图中得出以下信息:

  • 每1个Annotation对象,都会有唯一的RetentionPolicy属性。
  • 对于每 1 个 Annotation 对象,可以有若干个 ElementType 属性。
  • Annotation 有许多实现类,每一个实现类,都 和 1 个 RetentionPolicy 关联并且和 1~n 个 ElementType 关联

自定义注解

使用元注解自己定义的注解
JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用来修饰注解。

@Target

表明该注解可以应用的Java元素类型

Target类型描述
ElementType.TYPE用于类、接口(包括注解类型)、枚举
ElementType.FIELD用于属性(包括枚举中的常量)
ElementType.METHOD用于方法
ElementType.PARAMETER用于方法的形参
ElementType.CONSTRUCTOR用于构造函数
ElementType.LOCAL_VARIABLE用于局部变量
ElementType.ANNOTATION_TYPE用于注解类型
ElementType.PACKAGE用于包
ElementType.TYPE_PARAMETER1.8版本新增,用于类型变量
ElementType.TYPE_USE1.8版本新增,用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

@Retention

表明该注解的生命周期

生命周期类型描述
RetentionPolicy.SOURCE编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASSJVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME由JVM 加载,包含在类文件中,在运行时可以被获取到

@Document

表明该注解标记的元素可以被Javadoc 或类似的工具文档化

@Inherited

表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解

注解格式

/**
 * 修饰符 @interface 注解名 {
 * 注解元素的声明1
 * 注解元素的声明2
 * }
 * 修饰符:访问修饰符必须为public,不写默认为pubic;
 * 关键字:必须为@interface;
 * 注解名: 注解名称为自定义注解的名称,使用时还会用到;
 * 注解类型元素:注解类型元素是注解中内容,可以理解成自定义接口的实现部分;
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyTestAnnotation {
    /**
     *    注解的元素声明的两种形式
     *    type elementName();
     *    type elementName() default value;  
     */
    String value() default "test";
}

注解的作用

  1. 编译检查
    Annotation具有“让编译器进行编译检查的作用”。
    例如,@SuppressWarnings, @Deprecated和@Override都具有编译检查作用。
  2. 在反射中使用Annotation
    在反射的Class, Method, Field等函数中,有许多于Annotation相关的接口。
    这也意味着,我们可以在反射中解析并使用Annotation。
  3. 根据Annotation生成帮助文档
    通过给Annotation注解加上@Documented标签,能使该Annotation标签出现在javadoc中。
  4. 能够帮忙查看查看代码
    通过@Override, @Deprecated等,我们能很方便的了解程序的大致结构。
    另外,我们也可以通过自定义Annotation来实现一些功能。
    5.注解处理器
    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE 5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。
  5. 在框架中的作用
    在开发Java程序,尤其是Java EE应用的时候,总是免不了与各种配置文件打交道。以Java EE中典型的S(pring)S(truts)H(ibernate)架构来说,Spring、Struts和Hibernate这三个框架都有自己的XML格式的配置文件。这些配置文件需要与Java源代码保存同步,否则的话就可能出现错误。而且这些错误有可能到了运行时刻才被发现。把同一份信息保存在两个地方,总是个坏的主意。理想的情况是在一个地方维护这些信息就好了。其它部分所需的信息则通过自动的方式来生成。JDK 5中引入了源代码中的注解(annotation)这一机制。注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。注解的功能类似于代码中的注释,所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。
    因为注解大多都有自己的配置参数,而配置参数以名值对的方式出现,所以从某种角度来说,可以把注解看成是一个XML元素,该元素可以有不同的预定义的属性。
    而属性的值是可以在声明该元素的时候自行指定的。在代码中使用注解,就相当于把一部分元数据从XML文件移到了代码本身之中,在一个地方管理和维护。
    上面两段话其实已经阐述了java注解的主要作用之一,就是跟踪代码依赖性,实现替代配置文件功能。比较常见的是Spring等框架中的基于注解配置。现在的框架很多都使用了这种方式来减少配置文件的数量。基本上秉持着这么一个原则,与具体场景相关的配置应该使用注解的方式与数据关联,与具体场景无关的配置放于配置文件中。在另一方面我们还可以在通过设置注解的@Retention 级别在运行时使用反射对不同的注解进行处理。

实现自定义注解

1.定义自定义注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
    String value() default "test";
}

2.配置注解

@Data
@Builder
@MyAnnotation
public class MyBean {
    private String name;
    private Integer age;
}

3.利用反射解析注解

@Test
public void myAnnotationTest(){
    try {
        //获取MyBean的Class对象
        MyBean myBean = MyBean.builder().build();
        Class clazz = myBean.getClass();

        //判断myBean对象上是否有MyAnnotation注解
        if (clazz.isAnnotationPresent(MyAnnotation.class)) {
            System.out.println("MyBean类上配置了MyAnnotation注解!");
            //获取该对象上MyAnnotation类型的注解
            MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
            System.out.println(myAnnotation.value());
        } else {
            System.out.println("MyBean类上没有配置MyTAnnotation注解!");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4.运行结果

MyBean类上配置了MyAnnotation注解!
test

文章作者: nfLJ
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 nfLJ !
评论
 本篇
Java注解(Annotation) Java注解(Annotation)
概念Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类
2020-08-13
下一篇 
MyBatis简介 MyBatis简介
一、ORM简介JDBC是Java与数据库交互的统一API.传统的JDBC编程的操作步骤如下: (1)、注册数据库驱动,明确指定数据库URL地址、数据库用户名、密码等连接信息 (2)、通过DriverManager打开数据库连接 (3)、通
2020-08-11
  目录