Java Annotation

概况

本文主要介绍Java注解(Java Annotation)的概念、类型及使用等知识。

概念

基本知识

  • Java编程语言里,Java注解是一种可以被添加到Java源码里的元数据(metadata),尽管它们不是程序的一部分
  • 类(Classes)、方法(methods)、变量(variables)、参数(parameters)和包(packages)都可以被注解
  • Java注解从JDK 1.5开始被加入到Java中
  • Java注解对程序的执行没有影响

注解形式

  1. 使用@来告诉编译器,如@Entity告诉编译器注解的名字是Entity
  2. 注解可以包含元素

    • 这些元素对名称没有要求,可以有值,如

      1
      2
      3
      4
      5
      @Author {
      name = "Benjamin Franklin"
      data = "3/27/2003"
      }
      class MyClass {...}
    • 如果只有一个带值的元素,其名称可以被忽略,如

      1
      2
      @SuppressWarning("unchecked")
      voido myMethod() {...}
    • 如果没有元素,圆括号可以去掉,如@Override

  3. 在同一定义上也可以使用多个注解,如

    1
    2
    3
    @Author(name="Jane Doe")
    @EBook
    class MyClass {...}
  4. 如果注解有同一类型,则被称为重复注解(repeating annotation

类型

许多注解类型在Java SE API里预定义,一些注解类型用于Java编译器,一些应用到其它注解

应用到Java代码的注解

也称为内置注解(Built-in Annotations

  1. @Override:告知编译器该元素是为了覆盖定义在父类的元素,如果一个方法在父类或被实现接口中没有被发现,会引起编译器报错。如当覆盖子类的一个方法时,应该使用@Override来标记该方法,这样可以让代码可读,并且避免维护问题,例如当修改父类的方法签名时,开发人员必须修改子类中该方法的签名,否则编译器会抛出编译错误。当没有使用@Override时,会很难追踪到错误位置。见下面例子

    1
    2
    3
    4
    5
    6
    7
    8
    public class MyParentClass {
    public void justMethod() {...}
    }
    public class MyChildClass extends MyParentClass {
    @Override
    public void justMethod() {...}
    }
  2. @Deprecated:提示标记的元素(类、方法或域)过时了,应该不再使用。无论何时程序使用已经使用@Deprecated注解标记的方法、类或域时,编译器生成一个警告

  3. @SuppressWarnings:指示编译器忽略特殊的警告。如当在调用过时的方法(假定该方法使用@Deprecated标记)时,使用@SuppressWarnings注解来禁止派生的警告,如下代码所示

    1
    2
    @SuppressWarnings("deprecation")
    void method() {...}
  4. @SafeVarargs:在Java SE 7中引入,当应用到方法或构造函数时,声称代码不对其可变参数(varargs)的参数进行潜在的不安全操作。当该注解类型被使用时,关联到可变参数的unchecked警告被禁止

  5. @FunctionalInterface:在Java SE 8中引入,表明此类型声明是一个功能性接口

应用到其它注解的注解

也称为元注解(Meta Annotations

  1. @Retention:具体说明标记的注解如何被存储
    • RetentionPolicy.SOURCE:保留在源码里,被编译器忽略
    • RetentionPolicy.CLASS:被编译时的编译器保留,但被JVM忽略
    • RetentionPolicy.RUNTIME:被JVM保留,可以在运行时环境被使用(通过反射)
  2. @Documented:指明使用该注解的元素应该使用javadoc工具记录
  3. @Target:具体说明可以在何处使用该注解,如定义目标类型为METHOD,意味着该注解只能用在方法上

    • ElementType.ANNOTATION_TYPE:用于注解类型
    • ElementType.CONSTRUCTOR:用于构造函数
    • ElementType.FIELD:用于域或属性
    • ElementType.LOCAL_VARIABLE:用于局部变量
    • ElementType.METHOD:用于方法
    • ElementType.PACKAGE:用于包的定义
    • ElementType.PARAMETER:用于方法的参数
    • ElementType.TYPE:用于类的任意元素
    1
    2
    3
    4
    5
    6
    7
    @Target({ElementType.METHOD})
    public @interface MyCustomAnnotation {}
    public class MyClass {
    @MyCustomAnnotation
    public void myMethod() { // do sth }
    }
  4. @Inherited:指明在一个类里被使用的自定义注解应该被所有的子类继承,如下所示

    1
    2
    3
    4
    5
    6
    7
    @Inherited
    public @interface MyCustomAnnotation {}
    @MyCustomAnnotation
    public class MyParentClass {}
    public class MyChildClass extends MyParentClass {}
  5. @Repeatable:在Java SE 8中引入,具体指明该注解可以用于同一定义多次,如下所示

    1
    2
    3
    @Author(name="Jane Doe")
    @Author(name="John Smith")
    class MyClass {...}

使用

  1. 编译器信息Information for the compiler,被编译器用来检测错误或禁止警告;在Java中有三个内置的可用的注解(@Deprecated@Override@SupressWarning),能被用来提供某种指示给编译器
  2. 编译时和部署时处理Compile-time and deployment-time processing,软件工具可以处理注解信息来生成代码、XML文件等等
  3. 运行时处理Runtime processing,一些注解可用于在运行时被检测

参考方案

  1. Java annotations tutorial with examples
  2. Java annotation
  3. Java官方文档