requireNotNull vs уверен оператор !!в Котлине - PullRequest
0 голосов
/ 09 октября 2018

У нас есть приложение на основе Kotlin, и недавно мы добавили сторонние инструменты для проверки качества кода (Detekt in Codacy).Однако мы начали сталкиваться с ошибками UnsafeCallOnNullableType.Мы обнаружили, что подходящим подходом является добавление проверок requireNotNull для всех параметров, которые могут быть нулевыми.В настоящее время мы используем верный оператор (!!)

Есть ли у нас какая-либо конкретная причина или соглашение, чтобы выбрать одно из другого?Насколько я вижу, оба выбросят исключение и заблокируют поток выполнения, за исключением того, что один вызовет исключение IllegalArgumentException, а другой вызовет исключение NullPointerException.

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

requireNotNull, если вы ссылаетесь на Objects#requireNonNull, является Java-методом, эквивалентным !!, но с другим исключением.

Вы не добавили никакого кода, поэтомунемного трудно помочь вам отладить.Вы упомянули сторонние инструменты качества кода, но не какие.Я случайно наткнулся на эту проблему GH , которая соответствует вашей ошибке.Это также единственное, что я могу найти, чтобы в любой момент использовать именно эту ошибку.Я мог бы пропустить некоторые, но это тот, который охватывает главные хиты Google, поэтому я собираюсь остановиться на этом.

В проблеме упоминается, что OP использует Detekt через Codacy, что, кажется, соответствуетваша среда, а также.

Если вы используете Detekt, это сообщается об ошибке.Использование !! даже предложено IntelliJ.

Однако вы можете сделать это по-другому.

Да, использование Objects#requireNonNull является одним из вариантов.Хотя есть и второй, который использует нулевой безопасный оператор, как упоминалось в m0skit0.

Причина, по которой это работает, заключается в том, что если что-либо вызванное является нулевым, конечный результат будет нулевым.Т.е. это:

instance.nonNullType.nullable?.nullableChild?.someOtherNullableChild

Если какой-либо из значений Nullable равен NULL, окончательный результат равен NULL, а другие не называются.

Теперь, учитывая, что это, вероятно, ошибка вОбнаружить, это кажется самым простым обходным решением:

whatever.calls.you?.make?.to?.the?.database ?: throw NullPointerException("Something is null");

Он также сохраняет переменную не равной NULL, что означает, что вам не понадобятся вызовы, нулевые для безопасности, позже.Оператор elvis проверяет, является ли что-либо пустым, а затем выдает исключение.Кроме того, вы можете просто использовать Objects#requireNotNull:

Objects.requireNonNull(whatever.calls.you.make.to.the.database)

Если вам действительно нужно проверять каждый отдельный шаг, вам просто нужно хранить нулевые проверки везде

TL; DR:

!! и requireNotNull по сути одинаково работают, за исключением того, что requireNotNull является вызовом метода и !! компилируется в оператор if:

if(whatever == null) {
    Intrinsics.throwNpe();
}

Причина!! триггеры UnsafeCallOnNullableType из-за (вероятной) ошибки в Detekt (при условии, что вы используете ее прямо или косвенно).

0 голосов
/ 09 октября 2018

По моему опыту, лучшая практика, когда значение обнуляется, это использовать операторы ? и ?: и предоставлять альтернативу (если она доступна), когда значение равно нулю, например:

settings?.getValue("some-setting") ?: defaultValue

Обратите внимание, что это выражение вернет defaultValue, когда settings или getValue вернет ноль.

Лучше всего вообще избегать использования оператора !!, так как это в основном сводит на нет любую защиту от нулей,Когда это невозможно, я бы выбрал более всеобъемлющее исключение вместо того, чтобы полагаться на общие исключения, такие как IAE или NPE, например:

settings?.getValue("some-setting") ?: throw SettingNotFound("Descriptive message")
...