我需要在实现中再次使用@Nonnull吗?

19

虽然我认为应该有一个通用规则来确定是否继承注释,但我特别希望让FindBugs识别我的规则,因此这个问题是针对于FindBugs的。

据我所知,JavaDoc注释是从接口中获取的,在实现中会被忽略。这个概念对类似@Nonnull(或@NotNull)的注释也适用吗?

通过@Override注释,至少可以添加接口中不存在的其他注释。

以下情况会发生什么?FindBugs会识别它们吗?哪种情况更符合规范代码的要求?

  1. 接口使用@Nonnull,实现中使用@Override
  2. 接口使用@Nonnull,实现中使用@Override@Nonnull
  3. 接口没有注释,实现中使用@Override@Nonnull

我建议您澄清问题,表明您只对FindBugs感兴趣,而不是其他工具,或者表明您对任何空值检查工具的答案感兴趣。 - mernst
1
@mernst:有一个finbugs标签,我想知道FindBugs是否会识别它们所有。您建议在哪里添加FindBugs引用以使其更清晰? - Thomas Weller
标签表示问题与FindBugs相关,但仅添加标签并不意味着问题与FindBugs相关。大多数人会阅读您的问题标题和正文,而不是标签。 - mernst
@mernst:由于我不应该将它添加到标题中(http://meta.stackexchange.com/a/130208/273478),因此我已将其添加为我的问题的第一句话。 - Thomas Weller
2个回答

8

选择方案2:

  1. 接口@Nonnull,实现类@Override @Nonnull

如果工具能在正确的位置找到注解,则FindBugs等许多其他工具(如IDE)将更好地完成工作。正如JLS在此部分底部所述的那样:这些注解不会被继承。

注解继承仅适用于类(而不是方法、接口或构造函数)

因此,这些工具需要自行查找它们。有些工具确实这样做,但即使是FindBugs也没有始终这样做(上次我检查过是这样)。


我不明白为什么我们会在接口上放置@Nonnull,如果它不会被继承,你能详细说明一下吗? - Robert Bain
@RobertBain 嗯,接口定义了契约,而空值要求是契约的一部分。如果我们没有在接口上放置注释,那么只与接口一起工作的代码将不知道。 - barfuin

4

接口上的注释表示所有实现都不能返回 null,而实现中的注释则表明它遵循这个约定。它不是继承的,我认为任何一种都不是。

@CheckForNull 注释肯定不会被继承,因为子类可以缩小它们所接受的参数的 nullness,就像他们可以扩大返回类型的 nullness 一样。

interface Credentials {
    @NonNull
    String getPassword();

    void setPassword(@NonNull password);
}

// Allows null password
class GoodCreds implements Credentials {
    // but cannot widen; throw exception for null instead
    @Overrides
    @NonNull
    String getPassword() {...}

    // can widen parameters
    @Overrides
    void setPassword(@CheckForNull password) {...}
}

注意:我稍后会添加匹配用户名访问器来演示在BadCreds子类中的坏扩展。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接