本文将从重复注解的使用,获取以及设计思考三个方面来介绍重复注解。
重复注解的使用
在 JDK 8 以前,想要实现和重复注解相同的功能,可以编写如下代码:
@Schedules({@Schedule(time = "2020"), @Schedule(time="2021")})
public class Job {
public void execute(){
}
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedules {
Schedule value()[] ;
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedule {
String time();
}
那么,在 JDK 8 如何做呢?其实更简单,只需要为 Schedule
添加 @Repeatable(Schedules.class)
即可,如下所示。
@Schedules({@Schedule(time = "2020"), @Schedule(time="2021")})
public class Job {
@Schedule(time = "2020")
@Schedule(time="2021")
public void execute(){
}
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Schedules.class)
public @interface Schedule {
String time();
}
@Repeatable
是作为标记重复注解的元注解。
JDK 8 之所以如此设计重复注解, 是为了兼容性考虑,支持旧版本平滑升级。
如果是首次接触重复注解,为了支撑这项工作,编译器会为重复注解生成一个容器注解,也就是 @Repeatable
元注解中 value 所指定的注解类。所以需要再声明一个容器注解类,也就是上述的 @Schedules
。
容器注解类(Schedules
)必须含有一个数组类型的 value 元素,这个数组的类型还必须是重复注解的类型(Schedule
)。
重复注解的获取
上面介绍完了重复注解的使用,接下来介绍如何获取类或者方法上的重复注解。
重复注解的获取是通过实现了 AnnotatedElement
接口的对象来获取的,针对上述例子,可以通过如下方式获取:
Schedules annotation = Job.class.getAnnotation(Schedules.class);
try {
Method executeMethod = Job.class.getDeclaredMethod("execute");
Schedule declaredAnnotation = executeMethod.getAnnotation(Schedule.class);
Schedule[] annotationsByType = executeMethod.getAnnotationsByType(Schedule.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
需要注意的是在使用 getAnnotation(Class<T> annotationClass)
方法来获取重复注解,会返回 null
。所以,需要通过 Java 8 新增的方法 getAnnotationsByType(Class<T> annotationClass)
来获取重复注解。
设计思考
Java 官方文档中,建议在设计注解时,需要考虑清楚,因为现在注解的使用不仅可以是 0次 或 1次,还可以是多次。并且通过使用 @Target
元注释还能限制注解类型的使用位置。所以,仔细设计注解类型非常重要,我们需要确保使用我们所设计的注解的程序员能够发现它的灵活和强大。
写在最后
关于重复注解的使用,这里再做一个总结。使用重复注解,除了需要声明一个被 @Repeatable
元注解的所注解的重复注解外,还需要一个容器注解,并且容器注解需要有一个数组类型的 value元素,数组的类型必须为重复注解的类型。
这是 Java 8 系列的第三篇文章,前两篇分别介绍了比较亮眼的 Lambda 表达式 和 Stream,此篇则介绍了一个新的特性-重复注解。尽管不如前两个特性使用广泛,但作为新的语法,仍然需要知悉。如果你觉得我的文章还不错,并对后续文章感兴趣的话,或者说我们有什么能够交流分享的,可以通过扫描下方二维码来关注我的公众号!