"Condition is always false" 编译器发出警告,条件实际上可能为真

"Condition is always false" warning from the compiler on condition which can actually be true

我有一个接口,方法如下:

public interface MyInterface {
    void myMethod(@Nonnull String userEmail);
}

该接口具有以下实现:

public class MyInterfaceImpl implements MyInterface {
    @Override
    public void myMethod(@Nonnull String userEmail) {
        if ((userEmail== null) || !userEmail.endsWith("something")) {
            throw new SomeException("...");
        }
        ...
    }
}

编译器向我发出警告说 Condition 'userEmail == null' is always 'false',但这看起来不对。

据我了解,如果有人使用 null 值调用我的方法,注释 javax.annotation.Nonnull 将警告编译器,但如果有人传递空值,则不会阻止代码编译给它。所以是的,我的代码在某些时候可以用 null 值调用:


请注意,如果我在命令行上使用选项 -Xlint:all 进行编译,我会收到相同的警告(因此它看起来不像是我的 IDE 中的错误)。

有谁知道我怎样才能摆脱这个警告,为什么会出现这个警告?

免责声明:我展示的例子只是一个例子,实际代码在达到那个条件之前做了一些事情,但没有什么可以让 userEmail == null 总是 false (正如它所证明的那样我附加的调试器屏幕截图)。

您在方法参数上有注释。 @Nonnull String userEmail

因此它期望 userEmail== null 将始终计算为 false,因此没有理由在那里进行 if 检查。

检查 following answer 关于属于 JSR 305

@Nonnull

305 is about new annotations where you can already put them, which can help provide programmatic visibility into a design by contract system. So that if a certain method is supposed to not return null, or if a certain method is supposed to never receive a null parameter

那么如果你作为程序员有信心将那个参数注释为nonNull,为什么它不应该报告检查userEmail == null没有意义呢?使用注释就像您通知编译器您有信心它永远不会被 null 调用。

注解@Nonnull就像描述一个合同。您不会签订您知道可能会被破坏的合同。如果您不确定,请删除注释。如果您确定,请取消勾选 userEmail == null

正如很多人在评论中提到的那样。它的行为符合预期。 https://checkerframework.org/manual/#nullness-checker 的解释清楚地说明了这里发生的事情:

The checker issues a warning in these cases: When an expression of @NonNull type might become null, because it is a misuse of the type: the null value could flow to a dereference that the checker does not warn about.

以上警告仅在您将 -Alint=redundantNullComparison 传递给编译器时出现,并且默认情况下处于关闭状态。当您使用 -Xlint:all 进行编译时,甚至会启用此警告。

如果您不想在 itellij 上看到此警告,您可以更新您的设置:

设置(Ctrl+Alt+S / ) > Editor > Inspections > Java > Declaration redundancy > 使用明显非空参数调用空检查方法。

设置(Ctrl+Alt+S / ) > 构建、执行、部署 > 编译器 > 为非空注释方法和参数添加运行时断言

设置(Ctrl+Alt+S / ) > 编辑器 > 检查 > Java > 可能的错误

此外,如果您期望空值,那么首先使用该注释似乎不正确。