简体   繁体   中英

Google-guava checkNotNull and IntelliJ IDEA's “may produce java.lang.NullPointerException”

Is there any way to suppress this warning:

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 

I'm using IntelliJ IDEA 10.5 and I know this warning is unnecessary however I would like to suppress it just here and avoid switching inspections off.

Through a combination of @Contract annotations and the External Annotations feature, you can now annotate Preconditions methods such that IntelliJ applies the correct static analysis to calls to these methods.

Let's say we have this example

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
    }
}

In IntelliJ (I'm using 13):

  • Navigate to Preconditions.checkArgument(boolean) .
  • Place your cursor on the method name, and hit Alt - Enter to bring up the intentions popup.
  • Select "Add method contract".
  • Use the contract text false -> fail .
  • When prompted, provide a location for the External Annotations file.

Now the warning at someArg.doSomethingElse() goes away, and IDEA will, in fact, flag the if branch as always true!

Other contract texts:

  • Preconditions.checkArgument(boolean, String) should be false, _ -> fail
  • Preconditions.checkNotNull(Object, String) should be null, _ -> fail ,
  • etc, etc

Here is my full annotations.xml file for 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>

See Also

An old issue exists in JetBrains Yourtrack to add this type of functionality. I voted for it years ago, but I don't see an activity. If everyone votes for it, then we might get lucky.

To clarify the issue covers adding functionality so that you could tag a method as performing some type of null check. If that happened then you could write your own wrapper for the Preconditions method and annotate it.

UPDATE I got tired of waiting for the functionality so I submitted a patch myself. It is available in 12.1.1 build 129.239. To access the configuration: Settings > Inspections > Probable Bugs > Constant Conditions & Exceptions > Configure Assert/Check Methods.

Extract a method?

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

...

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

You can also assign returned value from checkNotNull method, which is non-null: 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());

From IntelliJ IDEA 14, you don't need to worry about this.

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

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

Earlier IntelliJ IDEA had no clue that code execution wouldn't even reach the “startsWith” call if the url is null because it didn't look inside StringUtils.isEmpty. You could of course remove those yellow warnings in extractPrefix by looking inside isEmpty yourself and adding a contract “null -> true”, but that's so boring, That's exactly a job for computer, not you, and now IntelliJ IDEA does it automatically. looking at byte and source code.

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

Apart from other options, you can try-

Suppress warnings at method level by using -

@SuppressWarnings({"NullableProblems"})
public void someMethod(){
   ...
   ...
}

or suppress warning at statement level by using comment -

//noinspection NullableProblems
someMethodCallProducingNullWarning(null);

But before doing this - make sure that it doesn't really produce NPE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM