Java @Google Guava函数接口中的可空输入触发FindBugs警告

Java @Google Guava函数接口中的可空输入触发FindBugs警告,java,guava,findbugs,Java,Guava,Findbugs,com.google.common.base.Function接口(from)将apply定义为: @Nullable T apply(@Nullable F input) 该方法具有以下javadoc注释: @如果{@code input}为null且此函数不接受null参数,则抛出NullPointerException FindBugs抱怨我的功能实现: private static final class Example implements Function<MyBean, St

com.google.common.base.Function
接口(from)将
apply
定义为:

@Nullable T apply(@Nullable F input)

该方法具有以下javadoc注释:

@如果{@code input}为null且此函数不接受null参数,则抛出NullPointerException

FindBugs抱怨我的功能实现:

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;
    }
}
private静态最终类示例实现函数{
@凌驾
@可空
公共字符串apply(@Nullable MyBean input){
if(null==输入){
抛出新的NullPointerException();
}
返回input.field;
}
}
具有高优先级的警告:

NP_参数_必须_为非空,但_标记为可空,优先级:高

输入必须为非Null,但标记为可为Null

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

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

在我看来,这似乎是一个矛盾:输入是@Nullable的,但方法@null时抛出NullPointerException。我错过什么了吗

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


谁对@Nullable annotation、FindBugs、Guava或我的用法有错?

您的实现是错误的;)

基本上,docs说(我将解释并强调):

@如果
input
为空且具体值为空,则抛出NullPointerException
函数实现不接受空参数

通过实现函数,您必须决定它是否接受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静态最终类示例实现函数{
@凌驾
@可空
公共字符串apply(@Nullable MyBean input){
返回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;
    }
}
private静态最终类示例实现函数{
@凌驾
@可空
公共字符串应用(MyBean输入){
if(null==输入){
抛出新的NullPointerException();
}
返回input.field;
}
}
在这两个示例中,都允许返回null

编辑:

请注意,Guava在所有包上默认使用
@javax.annotation.ParametersAreNonnull
,因此如果存在
@Nullable
,则表示“挂起全局
@Nonnull
并允许此处为空”,否则表示“此处禁止为空”

也就是说,您可能希望在参数上使用
@Nonnull
注释,或者在包中使用
@parameters默认情况下为nonnully
,告诉FindBugs函数的参数不能为null

编辑2:

事实证明,见评论3(来自Guava的负责人dev Kevin Bourrillion,关于他与Findbugs的负责人Bill Pugh的对话):

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


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

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

new Function<Object, Object>() {
            @Nonnull
            public Object apply(@Nonnull Object object) {
新函数(){
@非空
公共对象应用(@Nonnull对象){

现在Findbugs很高兴。谢谢大家

你说你将接受签名中的null,然后你拒绝了正文中的null值。听起来你好像误解了
@Nullable
的目的。我为输入参数添加
@Nullable
的唯一原因是它是
函数
接口定义的s、 无论如何,我按照@Xaerxess的建议从参数中删除了
@Nullable
注释,但FindBugs一直在抱怨。如果不从接口中删除注释,则将其添加到实现中。如果
函数
允许您使用null作为参数,这并不意味着您必须在impl中允许null,就像
函数
合同状态。注释已由框架接口指定,我无法(也不打算)从中删除。我唯一可以编辑的代码是我自己的代码(=实现)。我从实现中删除了@Nullable注释,但FindBugs一直在抱怨。标记为
@javax.annotation.Nonnull
-但没有帮助,仍然得到
此参数的使用方式始终要求它为非Null,但该参数被显式注释为可为Null。
@vitaly似乎这是一个错误这可能取决于您使用的FindBugs版本。您使用的是FindBugs 2.X,根据Guava的问题,我会说它是FindBugs 2.X bug;)