Google-guava checkNotNull和IntelliJ IDEA的“可能产生java.lang.NullPointerException”

时间:2011-07-06 14:39:37

标签: intellij-idea nullpointerexception guava inspection

有没有办法压制此警告:

MyClass object = null;

/*Some code that 'might' set this object but I know it will*/      


Preconditions.checkNotNull(object); 
//when "assert object != null" is used here no warning is shown

merged.setName(dRElement.getName());
//"May produce 'java.lang.NullPointerException'" warning here 

我正在使用IntelliJ IDEA 10.5,我知道这个警告是不必要的,但是我想在这里取消它,避免关闭切换检查。

6 个答案:

答案 0 :(得分:32)

通过@Contract注释和外部注释功能的组合,您现在可以注释Preconditions方法,以便IntelliJ将正确的静态分析应用于对这些方法的调用。

我们说我们有这个例子

public void doSomething(Object someArg) {
    Preconditions.checkArgument(someArg != null);
    someArg.doSomethingElse();  //currently gives NPE warning

    if (someArg != null) {
        //no warning that this is always true
    }
}

在IntelliJ中(我使用13):

  • 导航至Preconditions.checkArgument(boolean)
  • 将光标放在方法名称上,然后按 Alt - Enter 以显示意图弹出窗口。
  • 选择"添加方法合同"。
  • 使用合同文本false -> fail
  • 出现提示时,请提供“外部注释”文件的位置。

现在someArg.doSomethingElse()处的警告消失了,IDEA实际上会将if分支标记为始终为真!

其他合同文本:

  • Preconditions.checkArgument(boolean, String)应为false, _ -> fail
  • Preconditions.checkNotNull(Object, String)应为null, _ -> fail
  • 等等

以下是annotations.xml的完整Preconditions文件:

<root>
    <item name='com.google.common.base.Preconditions T checkNotNull(T)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions T checkNotNull(T, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions T checkNotNull(T, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
</root>

另见

答案 1 :(得分:15)

old issue exists in JetBrains Yourtrack添加此类功能。我几年前投票支持它,但我没有看到任何活动。如果每个人都投票,那么我们可能会很幸运。

澄清问题包括添加功能,以便您可以将方法标记为执行某种类型的空检查。如果发生这种情况,那么您可以为Preconditions方法编写自己的包装器并对其进行注释。

<强>更新 我厌倦了等待功能,所以我自己提交了一个补丁。它在12.1.1 build 129.239中提供。要访问配置:设置&gt;检查&gt;可能的错误&gt;恒定条件&amp;例外&gt;配置断言/检查方法。

答案 2 :(得分:2)

提取方法?

private MyClass getMyClass() {
    /* This always returns an instance of MyClass, never null. */      
}

...

MyClass object = getMyClass();
Preconditions.checkNotNull(object);
merged.setName(object.getName());

答案 3 :(得分:1)

您还可以从checkNotNull方法分配返回值,该方法为非空:http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Preconditions.html#checkNotNull(T)

MyClass object = null;
object = Preconditions.checkNotNull(object); 
merged.setName(dRElement.getName());

答案 4 :(得分:1)

从IntelliJ IDEA 14开始,您无需担心这一点。

@Nullable
String extractPrefix(@Nullable String url) {
    if (StringUtils.isEmpty(url)) return null;

    if (url.startsWith("jar://")) {
...
  

早期的IntelliJ IDEA没有任何线索,如果url为null,代码执行甚至不会到达“startsWith”调用,因为它没有查看StringUtils.isEmpty内部。您当然可以通过查看isEmpty并添加合同“null - &gt;”来删除extractPrefix中的黄色警告。真的“,但那太无聊了!这完全是计算机的工作,而不是你,现在IntelliJ IDEA自动完成,查看字节和源代码。

http://blog.jetbrains.com/idea/2014/10/automatic-notnullnullablecontract-inference-in-intellij-idea-14/

答案 5 :(得分:0)

除了其他选项,您可以尝试 -

使用 -

在方法级别抑制警告
@SuppressWarnings({"NullableProblems"})
public void someMethod(){
   ...
   ...
}

或使用评论 -

在声明级别禁止警告
//noinspection NullableProblems
someMethodCallProducingNullWarning(null);

但在此之前 - 确保它不会真正产生NPE