为什么我在进行空值检查时仍会收到 IntelliJ 中可能存在 NPE 的警告?

Why do I still receive warning for possible NPE in IntelliJ when I do my null checking?

我有一个函数可以 return 空值。所以我使用了 JetBrains 注释并在函数顶部放置了一个 @Nullable 注释。

@Nullable
public static ConnectionManager getConnectionManager() {
    return connectionManager;
}

然后,我 运行进行了 Lint 检查。当我使用这个函数时,我发现了 4 个地方,但我没有做任何 null 检查。

之前:

Service.getConnectionManager().onAssetInfoChanged();

之后:

if(Service.getConnectionManager() != null) {
    Service.getConnectionManager().onAssetInfoChanged();
}

然后我运行再次检查Lint。令我大吃一惊的是,我仍然得到:

Method invocation 'Service.getConnectionManager().onAssetInfoChanged()' at line 308 may produce 'java.lang.NullPointerException'.

我做错了什么?这是 Lint 检查器中的错误吗?

检查员并没有完全错。在这种情况下,您可能会有一个 NullPointerException:因为您每次都在调用 Service.getConnectionManager(),所以我们无法绝对确定它不会 return null 第二次,即使不是第一次:getter 的逻辑可能比 return ... 更复杂,或者变量可能已在两个方法之间同时设置为 null来电。

因此,您可以将代码重构为:

ConnectionManager manager = Service.getConnectionManager();
if (manager != null) {
    manager.onAssetInfoChanged();
}

假设getConnectionManager()的return类型是ConnectionManager类型的对象。有了这个,就不可能在该行上有一个 NullPointerException

问题是您调用了 Service.getConnectionManager() 两次。在您实际使用它的第二次调用时,Lint 必须假设它现在可以为空。解决这个问题的一种方法是使用这样的局部变量:

ConnectionManager connectionManager = Service.getConnectionManager();
if(connectionManager != null) {
    connectionManager.onAssetInfoChanged();
}

另一种方法,在我看来,首选方法是首先避免空值。如果您使用 Java 8,您可以使用 Optional 来表示您的 ConnectionManager 可以为空的事实。

最好的方法是确保您的 ConnectionManager 实际上永远不会 null

首先,@Nullable与可以为空的方法参数有关。相反的是NotNull,表示必须设置参数。其次,getConnectionManager 的每个调用都由分析器单独处理。这样做

ConnectionManager connManager = Service.getConnectionManager();
if(connManager != null
{
//do your stuff
}