Java 为什么@Repeatable注释不能从接口继承

Java 为什么@Repeatable注释不能从接口继承,java,inheritance,annotations,java-8,Java,Inheritance,Annotations,Java 8,在Java中,标记为的注释仅在注释类时有效: 请注意,如果已注释的 类型用于注释除类以外的任何内容。还请注意 此元注释只会导致从中继承注释 超类;已实现接口上的注释无效 因此,使用@Inherited注释注释的接口或方法不会导致实现也使用注释注释的类/方法。这样做的原因很可能是,如果类层次结构中有多个注释,那么编译器将不知道选择哪个注释 现在Java8引入了新的注释。我认为,对于标记为@inheritable和@Repeatable的注释,删除上述限制是很自然的,因为编译器应该能够将冲突的注释添

在Java中,标记为的注释仅在注释类时有效:

请注意,如果已注释的 类型用于注释除类以外的任何内容。还请注意 此元注释只会导致从中继承注释 超类;已实现接口上的注释无效

因此,使用
@Inherited
注释注释的接口或方法不会导致实现也使用注释注释的类/方法。这样做的原因很可能是,如果类层次结构中有多个注释,那么编译器将不知道选择哪个注释

现在Java8引入了新的注释。我认为,对于标记为
@inheritable
@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
,但它“只是”
CD
(即
@Inherited
的工作原理与Java 8之前的版本完全相同)

有人知道在Java 8的
@Repeatable
注释中,是否有充分的理由不删除关于接口和方法的
@继承的
限制


对于上述类型层次结构,是否有任何变通方法来实现输出?(除了使用反射扫描超级接口的注释…)

请回想以下文档:

如果注释类型声明中存在继承的元注释,并且用户在类声明中查询注释类型,,并且该类声明没有此类型的注释,则该类的超类将自动查询注释类型

换句话说,
@Inherited
从来不是用来收集类型层次结构上的多个注释的功能。相反,您将获得具有显式注释的最特定类型的注释

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

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

@RepeatableAnnotation("C") @RepeatableAnnotation("D")
public class TestClass extends Base implements IntefaceA, IntefaceB {
它不会改变结果<
TestClass
不会继承
Base
的code>FOO
BAR
,因为它具有显式注释值
C
D

将其扩展到
接口
层次结构会很尴尬,因为存在多重继承,而且一个超级接口可能是另一个超级接口的子接口,因此找到最具体的接口并不容易。这与超类层次结构的线性搜索有很大不同

您可能会遇到这样的情况,即存在多个不相关的带注释的
接口
s,但不清楚为什么应该通过将它们合并到一个重复注释中来解决这种歧义。这与所有其他场景中的行为不一致



请注意,有点奇怪,因为它显示使用方法注释的代码,但方法注释永远不会被继承,不管您是否指定了
@inherited
(当您将
@Target(ElementType.method)
@inherited
,imho组合时,审核工具应该生成警告)
@Inherited
仅与类型批注相关。

非常感谢您提供的详细答案<代码>将其扩展到接口层次结构会很尴尬,因为存在多重继承,而且超级接口可能是另一个超级接口的子接口,因此找到最具体的接口并不容易。
你说得对-我没有想到这种可能性。无论如何,我真的希望看到一个类似于Java中接口和方法的@Inherited注释的特性。