当我进行空检查时,为什么还会在IntelliJ中收到可能的NPE警告?

时间:2016-01-14 15:06:54

标签: java intellij-idea nullpointerexception lint intellij-15

我有一个可以返回null值的函数。所以我使用JetBrains注释并在函数顶部放置@Nullable注释。

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

然后,我进行了一次Lint检查。当我使用这个功能时,我找到了4个位置,我没有进行任何空检查。

在:

Service.getConnectionManager().onAssetInfoChanged();

后:

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

然后我再次进行Lint检查。令我惊讶的是,我仍然得到:

  

方法调用' Service.getConnectionManager().onAssetInfoChanged()'第308行可能会产生' java.lang.NullPointerException'。

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

3 个答案:

答案 0 :(得分:4)

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

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

null

假设ConnectionManager manager = Service.getConnectionManager(); if (manager != null) { manager.onAssetInfoChanged(); } 的返回类型是getConnectionManager()类型的对象。有了这个,就不可能在该行上有ConnectionManager

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:1)

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

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