The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
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运行方法doPeriodicCleanup。To 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.为了让编译器做到这一点,代码中需要两个声明。
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.对声明应用相同的批注而不首先将其声明为可重复会导致编译时错误。
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(); }
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类规范。
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元批注来限制批注类型的使用位置。@Target
meta-annotation.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.仔细设计批注类型非常重要,以确保使用批注的程序员发现它尽可能灵活和强大。