重复注解
注解(Annotation )是Java 5 推出来的,推出来后使用极其广泛,一些流行的框架基本都会用到注解实现一些功能,代替以前的配置方式,最典型的像Spring
。
在继续往下讲之前,我先声明你得知道注解的知识,我假设你已经掌握注解知识并能够自定义注解。
在Java 8 之前,同一个注解是不能在一个位置上重复使用的,例如我定义了一个注解@MyAnnotation
package edu.jyu.java8;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) // 使用范围在类、接口和枚举
@Retention(RetentionPolicy.RUNTIME) // 生命周期在运行时期,可以进行反射操作
public @interface MyAnnotation {
String value();// 定义一个属性值
}
然后定义了一个类Main
,在该类上重复使用注解@MyAnnotation
,编译时会报错
package edu.jyu.java8;
@MyAnnotation("Hello")
@MyAnnotation("World")
public class Main {
}
如果一定要在这个类上多次使用注解@MyAnnotation
,按照以前的做法,我们需要定义一个注解容器,顾名思义是存放注解的,如我定义一个注解容器@MyAnnotationContainer
,它的value
属性是一个MyAnnotation
数组
package edu.jyu.java8;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationContainer {
MyAnnotation[] value();
}
那么在Main
类上我就可以通过注解容器让Main
类多次使用@MyAnnotation
注解
package edu.jyu.java8;
@MyAnnotationContainer({ @MyAnnotation("Hello"), @MyAnnotation("World") })
public class Main {
}
其实严格上来说,上面的Main
并不是重复使用@MyAnnotation
注解,而是使用@MyAnnotationContainer
了。
而Java 8中提供了一个注解@Repeatable
,可以对用户隐藏掉注解容器,我只需要在@MyAnnotation
注解的定义上加上这个注解,如
package edu.jyu.java8;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) // 使用范围在类、接口和枚举
@Retention(RetentionPolicy.RUNTIME) // 生命周期在运行时期,可以进行反射操作
@Repeatable(MyAnnotationContainer.class) // 重复注解,需要指定注解容器
public @interface MyAnnotation {
String value();// 定义一个属性值
}
需要注意的是,@Repeatable
注解是需要一个注解容器的。现在Main
类中我就可以直接重复使用@MyAnnotation
注解了
package edu.jyu.java8;
import java.util.Arrays;
@MyAnnotation("Hello")
@MyAnnotation("World")
public class Main {
public static void main(String[] args) {
Class<Main> clazz = Main.class;
// 根据注解类型获取Main类上的所有注解
MyAnnotation[] annotations = clazz.getAnnotationsByType(MyAnnotation.class);
// 输出找到的所有注解
Arrays.stream(annotations)//
.forEach(System.out::println);
}
}
main
方法执行结果
@edu.jyu.java8.MyAnnotation(value=Hello)
@edu.jyu.java8.MyAnnotation(value=World)
输出找到的所有注解的代码是Java 8提供的Stream API和方法引用特性,还不了解的可以去看看我的其它Java 8特性文章