我要当国王无广告版
24.16 MB · 2025-12-19
java 中的可重复注解(Repeatable Annotation)是如何实现的使用可重复注解时,总是需要定义对应的 containing annotation。
假设我们定义了可重复注解 A,而它的 containing annotation 是 CA。
C 上使用了可重复注解 A (且它的 @Rentetion 的 value 是 RetentionPolicy.RUNTIME),那么
C.class 中会有 RuntimeVisibleAnnotations 属性CA 会出现在这个 RuntimeVisibleAnnotations 属性中CA 中会有若干 A 出现JDK 8 支持可重复注解(Repeatable Annotation)。在 Java Language Specification 中的 9.6.3. Repeatable Annotation Interfaces 小节 提到
大意是说,一个注解 A 是可重复注解,如果 A 上有 @Repeatable 元注解且 @Repeatable 的 value 的值是 A 的一个 containing annotation。
我写了一个简单的例子,请将以下代码保存为 PrimeNumber.java ⬇️
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Sample(value = 2)
@Sample(value = 3)
@Sample(value = 5)
@Sample(value = 7)
public class PrimeNumber {
public static void main(String[] args) throws NoSuchMethodException {
// 下面这行的 sample 会是 null
Sample sample = PrimeNumber.class.getAnnotation(Sample.class);
System.out.println(sample == null);
// 下面这行的 samples 中会有 4 个元素
Sample[] samples = PrimeNumber.class.getAnnotationsByType(Sample.class);
System.out.println(samples.length);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Samples.class)
@interface Sample {
int value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Samples {
Sample[] value();
}
这里的 @Sample 注解是可重复注解,而 Samples 是对应的 containing annotation。
以下命令可以编译 PrimeNumber.java 并运行其中的 main(...) 方法。
javac PrimeNumber.java
java PrimeNumber
运行结果如下 ⬇️
true
4
在编译之后,我们会得到 PrimeNumber.class 文件,用以下命令可以查看 PrimeNumber.class 的内容 ⬇️
javap -v -p PrimeNumber
完整的结果有点长,结尾部分的内容如下 ⬇️
RuntimeVisibleAnnotations:
0: #51(#52=[@#53(#52=I#54),@#53(#52=I#55),@#53(#52=I#56),@#53(#52=I#57)])
Samples(
value=[@Sample(
value=2
),@Sample(
value=3
),@Sample(
value=5
),@Sample(
value=7
)]
)
从中可以看出,在 RuntimeVisibleAnnotations 这个属性中,保存的是 @Samples 注解(这个注解中包含了 4 个 @Sample 注解)。
containing annotation 的例子我们也可以直接使用 @Samples 注解。
请将以下代码保存为 PrimeNumber2.java
@Samples(value = {
@Sample(value = 2),
@Sample(value = 3),
@Sample(value = 5),
@Sample(value = 7)
})
public class PrimeNumber2 {
}
用以下命令可以编译 PrimeNumber2.java
javac PrimeNumber2.java
编译后,我们会得到 PrimeNumber2.class 文件,用以下命令可以查看 PrimeNumber.class 的内容 ⬇️
javap -v -p PrimeNumber2
完整的结果有点长,结尾部分的内容如下 ⬇️
RuntimeVisibleAnnotations:
0: #14(#15=[@#16(#15=I#17),@#16(#15=I#18),@#16(#15=I#19),@#16(#15=I#20)])
Samples(
value=[@Sample(
value=2
),@Sample(
value=3
),@Sample(
value=5
),@Sample(
value=7
)]
)
这里的 RuntimeVisibleAnnotations 属性的内容,和 PrimeNumber.class 中 RuntimeVisibleAnnotations 属性的内容是一致的。由此可见,以下两种情况在 class 中的表示方式是一致的
containing annotationRuntimeVisibleAnnotations Attribute