35

com.google.common.base.Function接口(来自Google Guava)定义apply为:

@Nullable T apply(@Nullable F input);

该方法具有以下 javadoc 注释:

@throws NullPointerException if {@code input} is null and this function does not accept null arguments.

FindBugs 抱怨我的 Function 实现:

private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(@Nullable MyBean input) {
        if (null == input) {
            throw new NullPointerException();
        }
        return input.field;
    }
}

带有高优先级警告:

NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE,优先级:高

输入必须为非空,但被标记为可为空

此参数始终以要求它为非空的方式使用,但该参数被显式注释为可空。参数的使用或注释的使用是错误的。

我的函数不支持null输入,如果是这种情况,则会引发异常。如果我理解正确,FindBugs 将此视为非空的要求。

对我来说,这看起来很矛盾:输入是@Nullable,但是当它为空时方法@throws NullPointerException。我错过了什么吗?

摆脱我能看到的警告的唯一方法是手动抑制。(显然,番石榴代码超出了我的控制范围)。

@Nullable 注解、FindBugs、Guava 还是我自己的用法谁错了?

4

3 回答 3

28

你的实现是错误的;)

基本上文档说(我会解释和强调):

@throws NullPointerExceptionifinput为 null 并且具体的函数实现不接受 null 参数

通过实现你的函数,你必须决定它是否接受空值。在第一种情况下:

private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(@Nullable MyBean input) {
        return input == null ? null : input.field;
    }
}

在第二种情况下:

private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(MyBean input) {
        if (null == input) {
            throw new NullPointerException();
        }
        return input.field;
    }
}

在这两个示例中,都允许返回 null。

编辑:

请注意,Guava 用于@javax.annotation.ParametersAreNonnullByDefault所有包,因此如果@Nullable存在则表示“暂停全局@Nonnull并在此处允许空值”,如果不存在则表示“此处禁止空值”。

也就是说,您可能希望@Nonnull在参数或包中使用注释@ParametersAreNonnullByDefault来告诉 FindBugs 函数的参数不能为空。

编辑2:

原来这种情况是已知问题,请参阅评论 #3(来自 Guava 的首席开发人员 Kevin Bourrillion,关于他与 Findbugs 的负责人 Bill Pugh 的对话):

我的参考是与比尔·普格的一系列面对面对话。他毫不含糊地断言,@Nullable这仅意味着某些子类型 可能接受 null。findbugs 为我们证明了这一点——我们的代码非常干净地通过了可空性检查(尽管我们应该再次检查,因为进行了这个特定的函数更改)。

于 2012-09-14T10:36:20.280 回答
4

标记参数@Nonnull解决了 findbugs 的问题。

于 2015-02-04T10:45:13.393 回答
0

似乎默认情况下,Google Guava 函数默认为 @Nullable - 当没有注释时,我收到 Findbugs 错误,指出“结果必须为非空,但被标记为可空”。以下列方式将@Nonnull 添加到函数声明有助于:

new Function<Object, Object>() {
            @Nonnull
            public Object apply(@Nonnull Object object) {

现在 Findbugs 很高兴。谢谢大家

于 2017-07-28T09:39:54.843 回答