文档

Java™教程
隐藏目录
重复注解
路径: 学习Java语言
课程: 注解

重复注解

有一些情况下,您希望将相同的注解应用于声明或类型使用。从Java SE 8版本开始,重复注解使您可以实现这一点。

例如,您正在编写代码以使用计时器服务,该服务使您可以在指定的时间或特定的计划下运行一个方法,类似于UNIX的cron服务。现在,您想设置一个计时器来运行一个名为doPeriodicCleanup的方法,在每个月的最后一天和每个星期五的晚上11点运行。为了设置计时器运行,创建一个@Schedule注解并将其两次应用于doPeriodicCleanup方法。第一次使用指定了每月的最后一天,第二次使用指定了星期五的晚上11点,如下面的代码示例所示:

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

前面的示例将一个注解应用于一个方法。您可以在任何可以使用标准注解的地方重复使用注解。例如,您有一个处理未经授权访问异常的类。您对该类进行了一个@Alert注解,其中一个注解用于管理者,另一个注解用于管理员:

@Alert(role="Manager")
@Alert(role="Administrator")
public class UnauthorizedAccessException extends SecurityException { ... }

出于兼容性的考虑,重复注解存储在Java编译器自动生成的容器注解中。为了让编译器这样做,您的代码中需要两个声明。

步骤1:声明可重复的注解类型

该注解类型必须用@Repeatable元注解标记。下面的示例定义了一个自定义的@Schedule可重复注解类型:

import java.lang.annotation.Repeatable;

@Repeatable(Schedules.class)
public @interface Schedule {
  String dayOfMonth() default "first";
  String dayOfWeek() default "Mon";
  int hour() default 12;
}

@Repeatable元注解的值(在括号中)是Java编译器生成的用于存储重复注解的容器注解的类型。在这个例子中,包含注解类型是Schedules,因此重复的@Schedule注解存储在一个@Schedules注解中。

在未将声明标记为可重复之前,将相同的注解应用于声明将导致编译时错误。

步骤2:声明包含注解类型

包含注解类型必须具有一个带有数组类型的value元素。数组类型的组件类型必须是可重复注解类型。以下是Schedules包含注解类型的声明:

public @interface Schedules {
    Schedule[] value();
}

检索注解

Reflection API中有几种可用的方法用于检索注解。返回单个注解的方法的行为,如AnnotatedElement.getAnnotation(Class<T>),在只有一个请求的类型的注解存在时返回一个注解,其行为不变。如果存在多个请求类型的注解,可以通过首先获取它们的容器注解来获取它们。这样,旧代码可以继续使用。Java SE 8中引入了其他方法,可以通过扫描容器注解一次性返回多个注解,如AnnotatedElement.getAnnotationsByType(Class<T>)。有关所有可用方法的信息,请参见AnnotatedElement类规范。

设计考虑

在设计注解类型时,必须考虑该类型的注解的基数。现在可以使用注解零次、一次,或者如果注解类型被标记为@Repeatable,则可以使用多次。还可以使用@Target元注解来限制注解类型的使用位置。例如,可以创建一个可重复使用的注解类型,只能用于方法和字段上。设计注解类型时要仔细考虑,以确保程序员在使用注解时能够发现它具有尽可能灵活和强大的功能。


上一页:类型注解和可插拔类型系统
下一页:问题和练习:注解