Вызов Optional # isPresent () в одной строке сообщается как не вызванный - PullRequest
0 голосов
/ 06 ноября 2018

Я запускаю SonarQube, чтобы проверить мой код, и обнаружил случай, в котором я не понимаю сообщенную ошибку.

Мой код:

private static final int BASE_ID = 100_000_000;
private boolean isValidId(Id id) {
    return id.asInteger().isPresent() && id.asInteger().get() >= BASE_ID;
}

Метод asInteger возвращает Optional<Integer>

Ошибка, которую я получаю от sonarqube: Call "Optional#isPresent()" before accessing the value. в обратной строке.

Я понимаю, что код в порядке, так как вторая часть if не будет выполнена, если первая ложна. Я знаю, что это можно решить с помощью .filter(..).isPresent(), но мне больше нравится этот способ.

Есть идеи, почему это случилось?

Ответы [ 4 ]

0 голосов
/ 21 марта 2019

Чтобы избежать этой проблемы, я использую iterator (). Next () обладает той же функциональностью, что и .get, но поставляется без проблемы isPresent ()!

0 голосов
/ 06 ноября 2018

Sonarqube не может гарантировать, что два вызова id.asInteger() возвращают один и тот же объект, например поскольку многопоточность могла изменить значение id между двумя вызовами, поэтому правильно указано, что присутствие не было должным образом проверено.

Измените код, чтобы сначала присвоить локальной переменной, чтобы гарантировать, что isPresent() и get() вызываются для одного и того же объекта:

private boolean isValidId(Id id) {
    Optional<Integer> idAsInteger = id.asInteger();
    return idAsInteger.isPresent() && idAsInteger.get() >= BASE_ID;
}
0 голосов
/ 06 ноября 2018

При работе с дополнительными устройствами следует избегать .isPresent и .get в максимально возможной степени. Использование этих методов не безопаснее, чем использование нулей и противоречит функциональному духу. Для функционального программирования и для безопасной альтернативы нулевых проверок созданы дополнительные функции.

SonarQube имеет только ограниченные возможности с его анализом. Обычно это не может исключать все виды ложных срабатываний. Этот случай на самом деле не является проблемой, поскольку не рекомендуется использовать Optionals таким способом.

0 голосов
/ 06 ноября 2018

Вы можете написать это как одно утверждение:

return id.asInteger()
         .map(x -> x >= BASE_ID)
         .orElse(false)

но сонар жалуется, потому что в данном случае это ложный положительный результат.

...