为什么@Repeatable Annotations不能从接口继承

时间:2015-01-08 13:54:15

标签: java inheritance annotations java-8

标记为@Inherited的Java注释仅在注释类时才有效:

  

请注意,如果带注释,则此元注释类型无效   type用于注释除类之外的任何内容。另请注意   这个元注释只会导致注释继承自   超;已实现的接口上的注释无效。

因此,使用@Inherited注释注释的接口或方法不会导致实现类/方法也可以使用注释进行注释。造成这种情况的原因很可能是编译器不知道选择哪个注释,如果类层次结构中有多个注释,如here所述。

现在Java 8引入了新的注释@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,但它只是“{”CD(即@Inherited的工作方式与Java 8之前完全相同)。

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

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

1 个答案:

答案 0 :(得分:4)

请回忆一下@Inherited的文档:

  

如果注释类型声明中存在Inherited元注释,并且用户在类声明上查询注释类型,并且类声明没有此类型的注释,那么该类的将自动查询超类的注释类型。

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

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

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

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

它不会改变结果; FOO的{​​{1}}和BAR不会被Base继承,因为它具有明确的注释值TestClassC

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

您可能会遇到多个不相关的带注释的interface存在的情况,但不清楚为什么应该通过将它们连接成一个重复的注释来解决这种歧义。这与所有其他情景中的行为无法协调。


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

相关问题