Documentation

The Java™ Tutorials
Hide TOC
Repeating Annotations重复批注
Trail: Learning the Java Language
Lesson: Annotations

Repeating Annotations重复批注

There are some situations where you want to apply the same annotation to a declaration or type use.在某些情况下,您希望对声明或类型使用应用相同的批注。As of the Java SE 8 release, repeating annotations enable you to do this.从JavaSE8发行版开始,重复批注使您能够做到这一点。

For example, you are writing code to use a timer service that enables you to run a method at a given time or on a certain schedule, similar to the UNIX cron service.例如,您正在编写代码以使用计时器服务,该服务使您能够在给定的时间或特定的时间表上运行方法,类似于UNIX cron服务。Now you want to set a timer to run a method, doPeriodicCleanup, on the last day of the month and on every Friday at 11:00 p.m.现在,您需要设置一个计时器,以便在每月的最后一天和每个星期五的晚上11:00运行方法doPeriodicCleanupTo set the timer to run, create an @Schedule annotation and apply it twice to the doPeriodicCleanup method.要将计时器设置为运行,请创建@Schedule批注并将其应用于doPeriodicCleanup方法两次。The first use specifies the last day of the month and the second specifies Friday at 11p.m., as shown in the following code example:第一个用法指定一个月的最后一天,第二个用法指定星期五晚上11点,如下面的代码示例所示:

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

The previous example applies an annotation to a method.上一个示例将批注应用于方法。You can repeat an annotation anywhere that you would use a standard annotation.可以在将使用标准批注的任何位置重复批注。For example, you have a class for handling unauthorized access exceptions.例如,您有一个用于处理未授权访问异常的类。You annotate the class with one @Alert annotation for managers and another for admins:您使用一个@Alert批注为管理员批注,另一个为管理员批注:

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

For compatibility reasons, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler.出于兼容性原因,重复批注存储在Java编译器自动生成的容器批注中。In order for the compiler to do this, two declarations are required in your code.为了让编译器做到这一点,代码中需要两个声明。

Step 1: Declare a Repeatable Annotation Type步骤1:声明可重复的批注类型

The annotation type must be marked with the @Repeatable meta-annotation.批注类型必须标记为@Repeatable元批注。The following example defines a custom @Schedule repeatable annotation type:以下示例定义了自定义@Schedule可重复批注类型:

import java.lang.annotation.Repeatable;

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

The value of the @Repeatable meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations.括号中@Repeatable元批注的值是Java编译器生成用于存储重复批注的容器批注的类型。In this example, the containing annotation type is Schedules, so repeating @Schedule annotations is stored in an @Schedules annotation.在本例中,包含的批注类型是Schedules,因此重复的@Schedule批注存储在@Schedules批注中。

Applying the same annotation to a declaration without first declaring it to be repeatable results in a compile-time error.对声明应用相同的批注而不首先将其声明为可重复会导致编译时错误。

Step 2: Declare the Containing Annotation Type步骤2:声明包含的批注类型

The containing annotation type must have a value element with an array type.包含批注类型的元素必须具有数组类型的value元素。The component type of the array type must be the repeatable annotation type.数组类型的组件类型必须是可重复的批注类型。The declaration for the Schedules containing annotation type is the following:包含批注类型的Schedules的声明如下:

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

Retrieving Annotations检索批注

There are several methods available in the Reflection API that can be used to retrieve annotations.反射API中有几种方法可用于检索批注。The behavior of the methods that return a single annotation, such as AnnotatedElement.getAnnotation(Class<T>), are unchanged in that they only return a single annotation if one annotation of the requested type is present.返回单个批注的方法的行为,例如AnnotatedElement.getAnnotation(Class<T>),保持不变,因为如果存在一个请求类型的批注,它们只返回一个批注。If more than one annotation of the requested type is present, you can obtain them by first getting their container annotation.如果存在多个请求类型的批注,则可以通过首先获取其容器批注来获取它们。In this way, legacy code continues to work.这样,遗留代码继续工作。Other methods were introduced in Java SE 8 that scan through the container annotation to return multiple annotations at once, such as AnnotatedElement.getAnnotationsByType(Class<T>).Java SE 8中引入了其他方法,这些方法扫描容器批注以一次返回多个批注,例如AnnotatedElement.getAnnotationsByType(Class<T>)See the AnnotatedElement class specification for information on all of the available methods.有关所有可用方法的信息,请参阅AnnotatedElement类规范。

Design Considerations设计考虑

When designing an annotation type, you must consider the cardinality of annotations of that type.在设计批注类型时,必须考虑该类型的批注的基数It is now possible to use an annotation zero times, once, or, if the annotation's type is marked as @Repeatable, more than once.现在可以使用批注零次、一次或多次(如果批注的类型标记为@Repeatable)。It is also possible to restrict where an annotation type can be used by using the @Target meta-annotation.还可以通过使用@Target元批注来限制批注类型的使用位置。For example, you can create a repeatable annotation type that can only be used on methods and fields.例如,可以创建只能在方法和字段上使用的可重复批注类型。It is important to design your annotation type carefully to ensure that the programmer using the annotation finds it to be as flexible and powerful as possible.仔细设计批注类型非常重要,以确保使用批注的程序员发现它尽可能灵活和强大。


Previous page: Type Annotations and Pluggable Type Systems
Next page: Questions and Exercises: Annotations