【问题标题】:Why java classes do not inherit annotations from implemented interfaces?为什么java类不从实现的接口继承注解?
【发布时间】:2011-06-12 08:39:38
【问题描述】:

我正在使用依赖注入框架(Guice 的 AOP 专门拦截一些方法调用)。我的类实现了一个接口,我想注释接口方法,以便框架可以选择正确的方法。即使注解类型使用Inherited注解实现类也不会继承Inherited的Java文档中所述的注解:

还要注意这个元注释 只会导致注释 从超类继承; 已实现接口的注释 没有效果。

这可能是什么原因?了解一个对象的类在运行时实现的所有接口并不是一件难事,所以这个决定背后一定有充分的理由。

【问题讨论】:

    标签: java inheritance interface annotations


    【解决方案1】:

    我会说原因是否则会出现多重继承问题。

    示例:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD) @Inherited
    public @interface Baz { String value(); }
    
    public interface Foo{
        @Baz("baz") void doStuff();
    }
    
    public interface Bar{
        @Baz("phleem") void doStuff();
    }
    
    public class Flipp{
        @Baz("flopp") public void doStuff(){}
    }
    
    public class MyClass extends Flipp implements Foo, Bar{}
    

    如果我这样做:

    MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()
    

    结果会怎样? “baz”、“phleem”还是“flopp”?


    因此,接口上的注释很少有用。

    【讨论】:

    • 接口注释只有在你有一个支持它们的框架时才有用。顺便说一句,在这个例子中 getAnnotation() 返回 null ;)
    • 我不知道,各位。在这种情况下(如果不存在拼写错误),我预计会出现类似The field value is ambiguous. 的编译器错误,就像两个接口声明具有不同值的相同常量一样。我知道这是 not 字段,但注释值在编译时得到全部解析,不是吗?我们在这里缺少的功能在许多情况下会非常有用。顺便说一句,很抱歉恢复旧帖子:)。
    • @Slanec 查看 Spring 资源的方式,了解 Spring 人员如何解决这些问题。见AnnotationUtils.findAnnotation(method, annotationType)
    • 我正在考虑写一些类似的东西。通过某种简单的缓存,这对我来说似乎是一种方法。谢谢!在上面的示例中,它将找到Foo 的注释(MyClass 没有注释,然后按照它们在implements 之后的顺序搜索和获取接口)并因此打印“baz”。酷。
    • @WChargin 是的,只用了 2 年的时间就有人发现了那个错字 :-)
    【解决方案2】:

    来自@Inherited 的Javadoc

    表示一个注解类型是自动继承的。如果 注释类型上存在继承的元注释 声明,用户查询类上的注解类型 声明,并且类声明对此没有注释 类型,则将自动查询该类的超类 注释类型。这个过程会一直重复,直到有注解 找到此类型,或者类层次结构(对象)的顶部是 到达。如果没有超类有这个类型的注解,那么 查询将表明有问题的类没有这样的注释。 请注意,如果已注释,则此元注释类型无效 type 用于注释除类以外的任何内容。另请注意 此元注释仅导致注释从 超类;已实现接口上的注释无效。

    另一方面,JSR 305 验证器执行某种继承查找。如果你有一个类的层次结构:

    //Person.java
    @Nonnull
     public Integer getAge() {...}
    
    //Student.java (inherits from Person)
    @Min(5)
    public Integer getAge() {...}
    

    那么Student.getAge() 上的有效验证是@Nonnull @Min(5)@Nonnull 没有 @Inherited 元注释。

    【讨论】:

    • 这个应该是选择的答案
    • 您的示例与您的回答相矛盾,即@Inherited 对类以外的任何内容都没有影响
    • @Inherited 仅在您在 Class 上使用注解时有效
    • 回答OP关于接口注释的问题怎么样!?
    猜你喜欢
    • 1970-01-01
    • 2018-05-28
    • 2012-05-14
    • 2021-01-29
    • 2015-08-03
    • 2014-09-09
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    相关资源
    最近更新 更多