Подтвердить что ты не робот

Google-guava checkNotNull и IntelliJ IDEA "могут создавать java.lang.NullPointerException"

Есть ли способ подавить это предупреждение:

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, и я знаю, что это предупреждение не нужно, но я хотел бы подавить его только здесь и не отключать проверки.

4b9b3361

Ответ 1

Благодаря сочетанию аннотаций @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, как всегда, true!

Другие тексты договоров:

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

См. также

Ответ 2

старая проблема существует в JetBrains Yourtrack, чтобы добавить этот тип функциональности. Я проголосовал за это несколько лет назад, но я не вижу активности. Если все голосуют за него, тогда нам повезет.

Чтобы прояснить проблему, добавьте функциональность, чтобы вы могли пометить метод как выполняющий некоторый тип нулевой проверки. Если это произошло, вы можете написать свою собственную оболочку для метода Preconditions и аннотировать ее.

UPDATE Я устал ждать функциональности, поэтому сам представил патч. Он доступен в 12.1.1 build 129.239. Чтобы получить доступ к конфигурации: Настройки > Инспекции > Вероятные ошибки > Константные условия и исключения > Настроить методы подтверждения/проверки.

Ответ 3

Извлечь метод?

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

...

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

Ответ 5

Из IntelliJ IDEA 14 вам не нужно беспокоиться об этом.

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

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

Раньше IntelliJ IDEA не знала, что выполнение кода даже не достигнет вызова "startsWith", если URL-адрес равен null, потому что он не смотрел внутри StringUtils.isEmpty. Конечно, вы можете удалить эти желтые предупреждения в extractPrefix, заглянув внутрь isEmpty самостоятельно и добавив контракт "null → true", но это так скучно! Это точно работа для компьютера, а не вы, и теперь IntelliJ IDEA делает это автоматически, глядя на байт и исходный код.

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

Ответ 6

Помимо других вариантов, вы можете попробовать:

Подавлять предупреждения на уровне метода с помощью -

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

или подавить предупреждение на уровне инструкции, используя комментарий -

//noinspection NullableProblems
someMethodCallProducingNullWarning(null);

Но прежде чем делать это - убедитесь, что на самом деле он не производит NPE