Google-guava checkNotNull и IntelliJ IDEA "могут создавать java.lang.NullPointerException" - PullRequest
35 голосов
/ 06 июля 2011

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

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 ]

32 голосов
/ 11 февраля 2014

С помощью комбинации @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 - Введите , чтобы вызвать всплывающее окно с намерениями.
  • Выберите «Добавить метод контракта».
  • Использовать текст договора 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>

См. Также

15 голосов
/ 07 июля 2011

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

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

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

2 голосов
/ 06 июля 2011

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

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

...

MyClass object = getMyClass();
Preconditions.checkNotNull(object);
merged.setName(object.getName());
1 голос
/ 27 ноября 2014

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

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

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

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

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

1 голос
/ 29 августа 2014

Вы также можете назначить возвращаемое значение из метода 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());
0 голосов
/ 07 июля 2011

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

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

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

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

//noinspection NullableProblems
someMethodCallProducingNullWarning(null);

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

...