为什么@Repeatable注解不能继承接口

Why can @Repeatable Annotations not be inherited from interfaces

在 Java 中标记为 @Inherited 的注释仅在注释 classes:

时有效

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

因此,使用 @Inherited 注释进行注释的接口或方法不会导致实现 classes/methods 也使用该注释进行注释。原因很可能是,如果 class 层次结构中有多个注释,如 here.

所述,编译器将不知道选择哪个注释

现在Java8引入了新的注解@Repeatable。我认为取消上述对标记为 @Inherited@Repeatable 的注释的限制是很自然的,因为编译器随后应该能够将冲突的注释添加到 @Repeatable注释。

给定以下示例:

import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@interface RepeatableAnnotations {
    RepeatableAnnotation[] value(); 
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Repeatable(RepeatableAnnotations.class)
@interface RepeatableAnnotation {
    String value();
}

@RepeatableAnnotation("A")
interface IntefaceA {}

@RepeatableAnnotation("B")
interface IntefaceB {}

@RepeatableAnnotation("C")
@RepeatableAnnotation("D")
public class TestClass implements IntefaceA, IntefaceB {
    public static void main(String[] args) {
        for (RepeatableAnnotation a : TestClass.class.getAnnotation(RepeatableAnnotations.class).value()) {
            System.out.print(a.value());
        }
    }
}

我会 希望 输出为 ABCD 但它是 "just" CD (即 @Inherited 正在工作完全像之前 Java 8).

有谁知道在 Java 8 的 @Repeatable 注释的情况下是否有充分的理由不删除关于接口和方法的 @Inherited 限制?

是否有任何解决方法可以实现上述类型层次结构的 ABCD 输出? (除了使用反射扫描注解的超级接口...)

请回忆@Inherited的文档:

If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type.

换句话说,@Inherited 从未打算成为在类型层次结构上收集多个注释的功能。相反,您将获得具有显式注释的最具体类型的注释。

换句话说,如果您将声明更改为

@RepeatableAnnotation("FOO") @RepeatableAnnotation("BAR") class Base {}

@RepeatableAnnotation("C") @RepeatableAnnotation("D")
public class TestClass extends Base implements IntefaceA, IntefaceB {

不会改变结果; BaseFOOBAR 未被 TestClass 继承,因为它具有显式注释值 CD.

将其扩展到 interface 层次结构会很尴尬,因为多重继承以及超级接口可能会变成另一个超级接口的子接口,因此要找到最具体的一个不是微不足道的。这与超类层次结构的线性搜索有很大不同。

您可能会遇到存在多个不相关的注释 interface 的情况,但不清楚为什么要通过将它们合并为一个重复注释来解决这种歧义。这与所有其他情况下的行为不一致。


请注意,answer you have linked 有点奇怪,因为它显示使用方法注释的代码,但方法注释永远不会被继承,无论您是否指定 @Inherited(审计工具应生成当您将 @Target(ElementType.METHOD)@Inherited 结合使用时发出警告,恕我直言)。 @Inherited 仅与类型注释相关。