@Repeatable
是 JDK1.8
增加的元注解,用于声明当前注解是可重复的。如果有没有声明 @Repeatable
,在同一个地方使用相同的注解将编译报错。
代码实践一下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
在类上多次使用 @Value
注解,会报错,代码无法编译。
// 此处会报编译错误
@Value(value = "B")
@Value(value = "C")
public class AnnotationClass {
}
使用 @Repeatable
1、在 @Value
注解上添加 @Repeatable
元注解,@Repeatable
里面的的值是 @Value
的集合注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
2、Values
注解,value
方法的返回值为 @Value
数组
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Values {
Value[] value();
}
经过改造之后,AnnotationClass
的编译错误消失了。
// 不再报错了
@Value(value = "B")
@Value(value = "C")
public class AnnotationClass {
}
使用反射获取注解
@Value(value = "B")
@Value(value = "C")
public class AnnotationClass {
public static void main(String[] args) throws Exception {
System.out.println(AnnotationClass.class.getAnnotation(Value.class));
Annotation[] annotations = AnnotationClass.class.getAnnotations();
System.out.println(annotations.length);
System.out.println(Arrays.toString(annotations));
}
}
输出结果如下,可以看到,虽然在代码上看,我们使用了两个 @Value
注解,但是直接获取 @Value
注解却没有获取到,而获取全部注解长度也只有 1
,这个注解就是 @Values
注解。从结果可以反推出,当使用多个注解时,JDK
会在编译期转换为 @Repeatable
中声明的集合注解。
null
1
[@Values(value=[@Value(value=B), @Value(value=C)])]
约束
- @Target 范围,单个注解范围必须大于等于集合注解。
@Value
范围比 @Values
大,正常编译
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Values {
Value[] value();
}
@Value
范围比 @Values
小,编译报错
// Target of container annotation 'Values' is not a subset of target of this annotation
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Values {
Value[] value();
}
- @Retention 范围,单个注解范围必须小于等于集合注解
SOURCE(源码) < CLASS (字节码) < RUNTIME(运行)
@Value
范围比 @Values
大,编译报错
// Container annotation 'Values' has shorter retention ('CLASS') than the contained annotation
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
@Documented
public @interface Values {
Value[] value();
}