Java注解

Javadoc(文档注释)

  • Java 支持 3 种注释,分别是单行注释、多行注释和文档注释。文档注释以/*开头,并以/结束,可以通过 Javadoc 生成 API 帮助文档,Java 帮助文档主要用来说明类、成员变量和方法的功能。
  • 文档注释只放在类、接口、成员变量、方法之前,因为 Javadoc 只处理这些地方的文档注释,而忽略其它地方的文档注释。
  • Javadoc 是 Sun 公司提供的一种工具,它可以从程序源代码中抽取类、方法、成员等注释,然后形成一个和源代码配套的 API 帮助文档。也就是说,只要在编写程序时以一套特定的标签注释,在程序编写完成后,通过 Javadoc 就形成了程序的 API 帮助文档。
  • API 帮助文档相当于产品说明书,而说明书只需要介绍那些供用户使用的部分,所以 Javadoc 默认只提取 public、protected 修饰的部分。如果要提取 private 修饰的部分,需要使用 -private。
  1. Javadoc标签

    • Javadoc 工具可以识别文档注释中的一些特殊标签,这些标签一般以@开头,后跟一个指定的名字,有的也以{@开头,以}结束。 | 标签 | 描述 | 示例 | | :—- | :—- | :—- | | @author | 标识一个类的作者,一般用于类注释 | @author description | | @deprecated | 指名一个过期的类或成员,表明该类或方法不建议使用 | @deprecated description | | {@docRoot} | 指明当前文档根目录的路径 | Directory Path | | @exception | 可能抛出异常的说明,一般用于方法注释 | @exception exception-name explanation | | {@inheritDoc} | 从直接父类继承的注释 | Inherits a comment from the immediate surperclass. | | {@link} | 插入一个到另一个主题的链接 | {@link name text} | | {@linkplain} | 插入一个到另一个主题的链接,但是该链接显示纯文本字体 | Inserts an in-line link to another topic. | | @param | 说明一个方法的参数,一般用于方法注释 | @param parameter-name explanation | | @return | 说明返回值类型,一般用于方法注释,不能出现再构造方法中 | @return explanation | | @see | 指定一个到另一个主题的链接 | @see anchor | | @serial | 说明一个序列化属性 | @serial description | | @serialData | 说明通过 writeObject() 和 writeExternal() 方法写的数据 | @serialData description | | @serialField | 说明一个 ObjectStreamField 组件 | @serialField name type description | | @since | 说明从哪个版本起开始有了这个函数 | @since release | | @throws | 和 @exception 标签一样 | . The @throws tag has the same meaning as the @exception tag. | | {@value} | 显示常量的值,该常量必须是 static 属性。 | Displays the value of a constant, which must be a static field. | | @version | 指定类的版本,一般用于类注释 | @version info |

    • 对两种标签格式的说明:

      • @tag 格式的标签(不被{ }包围的标签)为块标签,只能在主要描述(类注释中对该类的详细说明为主要描述)后面的标签部分(如果块标签放在主要描述的前面,则生成 API 帮助文档时会检测不到主要描述)。
      • {@tag} 格式的标签(由{ }包围的标签)为内联标签,可以放在主要描述中的任何位置或块标签的注释中。
    • Javadoc 标签注意事项:

      • Javadoc 标签必须从一行的开头开始,否则将被视为普通文本。
      • 一般具有相同名称的标签放在一起。
      • Javadoc 标签区分大小写,代码中对于大小写错误的标签不会发生编译错误,但是在生成 API 帮助文档时会检测不到该注释内容。
  2. 文档注释的格式

    1. 在编写文档注释的过程中,有时需要添加 HTML 标签,比如:需要换行时,应该使用
      ,而不是一个回车符;需要分段时,应该使用

    2. Javadoc 并不是将代码中的文档注释直接复制到帮助文档的 HTML 文件中,而是读取每一行后,删除前面的号及以前的空格再输入到 HTML 文档。
    3. 示例```java /**
    • first line. * second line.
    • third line. */ ```
  1. - 编译输出后的 HTML 源码```

first line.
second line.
third line.

  1. - 注释前面的_号允许连续使用多个,其效果和使用一个_号一样,但多个_前不能有其他字符分隔,否则分隔符及后面的_号都将作为文档的内容。
  2. <a name="1e0b3304"></a>
  3. ## Java架构
  4. ![](./JavaAnnotation/Annotation%E6%9E%B6%E6%9E%84.jpg#alt=)
  5. - 1 Annotation 1 RetentionPolicy 关联。可以理解为:每1Annotation对象,都会有唯一的RetentionPolicy属性。
  6. - 1 Annotation 1~n ElementType 关联。可以理解为:对于每 1 Annotation 对象,可以有若干个 ElementType 属性。
  7. - Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等。**Annotation 的每一个实现类,都 "和 1 个 RetentionPolicy 关联" 并且 " 和 1~n 个 ElementType 关联"**。
  8. <a name="abb76d97"></a>
  9. ## Annotation 组成部分
  10. 1. 三个类
  11. ```java
  12. public interface Annotation {
  13. boolean equals(Object obj);
  14. int hashCode();
  15. String toString();
  16. Class<? extends Annotation> annotationType();
  17. }
  18. public enum ElementType {
  19. TYPE, /* 类、接口(包括注释类型)或枚举声明 */
  20. FIELD, /* 字段声明(包括枚举常量) */
  21. METHOD, /* 方法声明 */
  22. PARAMETER, /* 参数声明 */
  23. CONSTRUCTOR, /* 构造方法声明 */
  24. LOCAL_VARIABLE, /* 局部变量声明 */
  25. ANNOTATION_TYPE, /* 注释类型声明 */
  26. PACKAGE /* 包声明 */
  27. }
  28. public enum RetentionPolicy {
  29. SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */
  30. CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */
  31. RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
  32. }
  1. 关联解释
  2. Annotation 就是个接口。

    • “每 1 个 Annotation” 都与 “1 个 RetentionPolicy” 关联,并且与 “1~n 个 ElementType” 关联。可以通俗的理解为:每 1 个 Annotation 对象,都会有唯一的 RetentionPolicy 属性;至于 ElementType 属性,则有 1~n 个。
  3. ElementType 是 Enum 枚举类型,它用来指定 Annotation 的类型。

    • “每 1 个 Annotation” 都与 “1~n 个 ElementType” 关联。当 Annotation 与某个 ElementType 关联时,就意味着:Annotation有了某种用途。
    • 例如,若一个 Annotation 对象是 METHOD 类型,则该 Annotation 能用来修饰方法。
  4. RetentionPolicy 是 Enum 枚举类型,它用来指定 Annotation 的策略。

    • 通俗点说,就是不同 RetentionPolicy 类型的 Annotation 的作用域不同。
    • “每 1 个 Annotation” 都与 “1 个 RetentionPolicy” 关联。

      1. 若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅存在于编译器处理期间,编译器处理完之后,该 Annotation 就没用了。

        • 例如,” @Override” 标志就是一个 Annotation。当它修饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编译期间会进行语法检查!编译器处理完后,”@Override” 就没有任何作用了。
      2. 若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件中,它是 Annotation 的默认行为。
      3. 若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,并且可由JVM读入。

Annotation 通用定义

  1. @Documented
  2. @Target(ElementType.TYPE)
  3. @Retention(RetentionPolicy.RUNTIME)
  4. public @interface MyAnnotation {
  5. }
  • 定义一个 Annotation,它的名字是 MyAnnotation
  • 可以在代码中通过 “@MyAnnotation” 来使用它
  1. @interface

    • 使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。
    • 定义 Annotation 时,@interface 是必须的
    • 注意:它和我们通常的 implemented 实现接口的方法不同。
    • Annotation 接口的实现细节都由编译器完成。
    • 通过 @interface 定义注解后,该注解不能继承其他的注解或接口。
  2. @Documented

    • 类和方法的 Annotation 在缺省情况下是不出现在 javadoc 中的。如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。
    • 定义 Annotation 时,@Documented 可有可无;
    • 若没有定义,则 Annotation 不会出现在 javadoc 中。
  3. @Target(ElementType.TYPE)

    • ElementType 是 Annotation 的类型属性。而 @Target 的作用,就是来指定 Annotation 的类型属性。
    • @Target(ElementType.TYPE) 的意思就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来修饰”类、接口(包括注释类型)或枚举声明”的注解。
    • 定义 Annotation 时,@Target 可有可无。若有 @Target,则该 Annotation 只能用于它所指定的地方;若没有 @Target,则该 Annotation 可以用于任何地方。
  4. @Retention(RetentionPolicy.RUNTIME)

    • RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的作用,就是指定 Annotation 的策略属性。
    • @Retention(RetentionPolicy.RUNTIME) 的意思就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 信息保留在 .class 文件中,并且能被虚拟机读取。
    • 定义 Annotation 时,@Retention 可有可无。若没有 @Retention,则默认是 RetentionPolicy.CLASS。
  5. @interface 用来声明 Annotation,@Documented 用来表示该 Annotation 是否会出现在 javadoc 中, @Target 用来指定 Annotation 的类型,@Retention 用来指定 Annotation 的策略。

Java基本注解

  1. 作用在其他注解的注解(元注解)

    1. @Retention(value = RetentionPolicy.RUNTIME)
    2. @Target(value = { ElementType.TYPE })
    3. @Documented
    4. @Inherited :只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。java @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Inherited { }
  1. 作用在代码的注解

    1. @Override :检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
    2. @Deprecated :标记过时方法。如果使用该方法,会报编译警告。java @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Deprecated { }
  1. @SuppressWarnings :指示编译器去忽略注解中声明的警告。java @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); }
  1. - String[] value(); 意味着,SuppressWarnings 能指定参数
  2. - SuppressWarnings 的作用是,让编译器对"它所标注的内容"的某些警告保持静默, @SuppressWarnings(value={"deprecation", "unchecked"})
  1. deprecation -- 使用了不赞成使用的类或方法时的警告
  2. unchecked -- 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。
  3. fallthrough -- Switch 程序块直接通往下一种情况而没有 Break 时的警告。
  4. path -- 在类路径、源文件路径等中有不存在的路径时的警告。
  5. serial -- 当在可序列化的类上缺少 serialVersionUID 定义时的警告。
  6. finally -- 任何 finally 子句不能正常完成时的警告。
  7. all -- 关于以上所有情况的警告。
  1. 额外添加了 3 个注解:

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

Annotation 的作用

  1. 编译检查 — @SuppressWarnings, @Deprecated @Override

  2. 在反射中使用 Annotation — 在反射中解析并使用 Annotation。

    1. /**
    2. * Annotation在反射函数中的使用示例
    3. */
    4. @Retention(RetentionPolicy.RUNTIME)
    5. @interface MyAnnotation {
    6. String[] value() default "unknown";
    7. }
    8. /**
    9. * Person类。它会使用MyAnnotation注解。
    10. */
    11. class Person {
    12. /**
    13. * sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
    14. * @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
    15. */
    16. @MyAnnotation(value={"girl","boy"})
    17. public void somebody(String name, int age){
    18. System.out.println("\nsomebody: "+name+", "+age);
    19. }
    20. }
    21. public class AnnotationTest {
    22. public static void main(String[] args) throws Exception {
    23. // 新建Person
    24. Person person = new Person();
    25. // 获取Person的Class实例
    26. Class<Person> c = Person.class;
    27. // 获取 somebody() 方法的Method实例
    28. Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
    29. // 执行该方法
    30. mSomebody.invoke(person, new Object[]{"lily", 18});
    31. // 判断 somebody() 方法是否包含MyAnnotation注解
    32. if(method.isAnnotationPresent(MyAnnotation.class)){
    33. // 获取该方法的MyAnnotation注解实例
    34. MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
    35. // 获取 myAnnotation的值,并打印出来
    36. String[] values = myAnnotation.value();
    37. for (String str:values)
    38. System.out.printf(str+", ");
    39. System.out.println();
    40. }
    41. }
    42. }
  1. 根据 Annotation 生成帮助文档 — @Documented

  2. 能够帮忙查看代码,了解程序的大致结构。 — @Override, @Deprecated

参数校验(javax.validation.constraints)

  1. @NotEmpty:不能为null或者长度为0(String、Collection、Map的isEmpty()方法)接受CharSequence(String类)、Collection、Map、数组。
  2. @NotBlank:带注释的元素不能为null,并且必须至少包含一个。非空白字符(纯空格的String也是不符合规则的),接受CharSequence(String类)。
  3. @NotNull:必须不为 null,接受任何类型
  4. @Null:必须为 null,,接受任何类型
  5. @AssertTrue:必须为 true,接受布尔类型
  6. @AssertFalse:必须为 false,接受布尔类型
  7. @Pattern(regex=,flag=):必须符合指定的正则表达式(符合java规定的表达式),接受CharSequence(String类),{@code null}元素被认为是有效的
  8. @Email:有格式良好的电子邮件地址(电子邮件地址留给Bean验证提供者),构成有效数据的确切语义(必须是 Email 格式)。接受CharSequence(String类)
  9. @Min(value):必须是一个数值,其值必须大于等于指定的最小值,支持BigDecimal、BigInteger、byte、short、int、long,不支持double、float(由于舍入误差),{@code null}元素被认为是有效的
  10. @Max(value):必须是一个数值,其值必须小于或等于指定的最大值,支持BigDecimal、BigInteger、byte、short、int、long,不支持double、float(由于舍入误差),{@code null}元素被认为是有效的
  11. @DecimalMin(value):必须是一个数值,其值必须大于等于指定的最小值,支持BigDecimal、BigInteger、byte、short、int、long、CharSequence(String类),不支持double、float(由于舍入误差),{@code null}元素被认为是有效的
  12. @DecimalMax(value):必须是一个数值,其值必须小于等于指定的最大值,支持BigDecimal、BigInteger、byte、short、int、long、CharSequence(String类),不支持double、float(由于舍入误差),{@code null}元素被认为是有效的
  13. @Size(max=, min=):元素size/length必须在指定的范围内,支持CharSequence(String类)、Collection、Map、array,{@code null}元素被认为是有效的
  14. @Digits (integer, fraction):必须是一个数值,其值必须在可接受的范围内,支持BigDecimal、BigInteger、byte、short、int、long、CharSequence(String类),{@code null}元素被认为是有效的
  15. @Past:必须是一个过去的日期
  16. @PastOrPresent
  17. @Future 被注释的元素必须是一个将来的日期
  18. @FutureOrPresent
  19. @Negative
  20. @NegativeOrZero
  21. @Positive
  22. PositiveOrZero