В чем разница между ненулевыми проверками в Котлине? - PullRequest
0 голосов
/ 26 декабря 2018

Есть несколько способов выполнить нулевую проверку в Kotlin:

1.

if(myVar != null) {
    foo(myVar)
}

2.

myVar?.let { 
    foo(it)
}

3.

myVar?.run { 
    foo(this)
}

В чем разница между этими способами?

Есть ли какие-либо причины (производительность, лучшие практики, стиль кода и т. Д.), Почему я должен отдавать предпочтение другим?

Ответы [ 7 ]

0 голосов
/ 26 декабря 2018

У Kotlin появились новые функции с NullPoint-Exception as Compare to Java.

В основном Когда мы делаем кодирование в Java, мы должны проверить с помощью !!в каждом Flying.

Но в Kotlin это простой способ реализовать First

как Like,

Предположим, в Kotlin

var response: Json? = Null

ответ: Json? .Let {

эта часть будет обрабатывать автоматически, если ответ не равен Null .... тогда выполнение этого блока начинается} ?. run {Это Nullable, но, где мы можем поставить Warring} Итак, я предлагаю вам, ребята, начать работу в Kotlin с этими функциями, предоставленными Kotlin.

(Flied) ?. let {Not Null Value is Under Under} ?. run {NullКод значения}

Это обработает исключение NullPoint или защитит ваше приложение для сбоя

0 голосов
/ 26 декабря 2018

Чего вы хотите добиться

Чего вы хотите достичь, так это того, что компилятор Kotlin выполняет умное приведение к переменной, с которой вы работаете.

Во всех ваших трех примерах компилятор может это сделать.

Пример:

if(myVar != null) {
    foo(myVar) // smart cast: the compiler knows, that myVar can never be null here
}

Выбор

Какой из нихиз вариантов использования, это действительно вопрос стиля.То, что вы не должны делать, это смешивать это часто.Используйте один и придерживайтесь его.

Вам не нужно беспокоиться о производительности, поскольку let и run встроены (см. встроенная функция ).Это означает, что их код (тело) копируется на сайт вызова во время компиляции, поэтому нет времени выполнения.

0 голосов
/ 26 декабря 2018

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

Другим способом использования свойства, допускающего нулевое значение, является безопасный оператор вызова?,Это вызывает метод, если свойство не является нулевым, или возвращает нуль, если это свойство является нулевым, не выбрасывая NPE (исключение нулевого указателя).

nullableVariable?.someMethodCall()
0 голосов
/ 26 декабря 2018

Примеры в вашем вопросе не показывают истинную причину решения.

Прежде всего, поскольку вы не используете возвращаемое значение foo, вы не должны использовать ни let, ниrun.Ваш выбор между also и apply.

Во-вторых, поскольку у вас уже есть результат, который вы хотите проверить в переменной на нуль, разница исчезает.Это лучший мотивирующий пример:

complexCall(calculateArg1(), calculateArg2())?.also {
    results.add(it)
}

, в отличие от

val result = complexCall(calculateArg1(), calculateArg2())
if (result != null) {
    results.add(result)
}

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

Первый пример, с другой стороны, сохраняет все автономным, и когда вы продолжаете читать остальную часть кода, вы на 100% уверены, что вам не нужно помнить о значенииresult.

0 голосов
/ 26 декабря 2018

Все три примерно эквивалентны.

Случай if больше похож на большинство других языков, и поэтому многие разработчики могут найти его более легким для чтения.

Однако, одно отличие состоит в том, чторегистр if будет считывать значение myVar дважды: один раз для проверки и еще раз при передаче его на foo().Это имеет значение, потому что, если myVar является свойством (то есть чем-то, что потенциально может быть изменено другим потоком), то компилятор предупредит, что ему может быть присвоено значение null после проверки.Если это проблема (например, потому что foo() ожидает ненулевой параметр), вам нужно будет использовать один из других случаев.

По этой причине случай let стал довольно распространеннымпрактиковаться в Котлине.(Случай run делает примерно то же самое, но по какой-то причине не так популярен для такого рода вещей. Я не знаю почему.)

Другой способ - назначить myVar к временному значению, проверьте это, а затем используйте это.Это также больше похоже на другие языки, но это более многословно;многие люди предпочитают краткость let, особенно когда myVar на самом деле сложное выражение.

0 голосов
/ 26 декабря 2018

Пути 2 и 3 более идиоматичны для Котлина.Обе функции довольно похожи.Существует небольшая разница с передачей аргументов.

Например, у нас есть переменная Nullable:

var canBeNull: String? = null

Когда вы работаете с T.run, вы работаете с вызовом функции расширения и передаете this в закрытии.

    canBeNull?.run {
        println(length) // `this` could be omitted
    }

Когда вы звоните T.let, вы можете использовать его как лямбда-аргумент it.

    canBeNull?.let {
        myString -> println(myString.length) // You could convert `it` to some other name
    }

Хорошая статья оСтандартные функции Kotlin.

0 голосов
/ 26 декабря 2018

Все три кода ведут себя одинаково с нулевой проверкой в ​​операционном отношении.

?.используется для цепных операций.

 bob?.department?.head?.name // if any of the properties in it is null it returns null

Чтобы выполнить цепную операцию только для ненулевых значений, вы можете использовать оператор безопасного вызова вместе с let

myVar?.let { 
foo(it)
}

приведенный выше кодподходит для стиля и производительности кода

подробнее см. Нулевая безопасность

...