#kotlin
#kotlin
Вопрос:
Недавно я начал изучать Kotlin. Одна вещь, которую я не могу понять, — это блоки проверки null. Следующий оператор считается небезопасным, и компилятор не позволит вам его скомпилировать.
var testVar: String? = null;
// if (testVar != null )
{
// Doing some work....
println(testVar.length)
}
Но когда вы раскомментируете if
строку, все работает. Это кажется отличным.
Но что, если // Doing some work....
это дорого с точки зрения вычислений, и другой поток изменяет значение testVar
to null
, пока этот поток находится в // Doing some work
очереди? В этом сценарии:
- Выдает ли программа исключение NullPointerException?
- или:
- Кэширует ли байт-код значение testVar и использует ли кэшированное значение внутри блока if?
Ответ №1:
В вашем первоначальном примере ваша var
локальная функция для функции? Например:
fun doStuff() {
var testVar: String? = null
if (testVar != null) {
println(testVar.length)
}
}
В этом случае ни одна другая область не имеет ссылки testVar
, поэтому ничто другое не может ее изменить. Однако, если это var
свойство класса, т.е.
class MyClass {
var testVar: String? = null
fun doStuff() {
if (testVar != null) {
println(testVar.length)
}
}
}
Это не удастся скомпилировать, поскольку testVar
другой поток мог установить значение null между проверкой и использованием.
Идем дальше, если вы пытаетесь быть хитрым:
fun doStuff() {
var testVar: String? = null
fun trickyFunction() {
testVar = null
}
if (testVar != null) {
trickyFunction()
println(testVar.length)
}
}
Компилятор завершится с ошибкой, поскольку ваша переменная будет захвачена изменяющимся замыканием. Итак, в общем, если вы можете использовать переменную с помощью интеллектуального приведения к ненулевому значению, вам не нужно беспокоиться о каких-либо потенциальных NPE.
Для второго сценария (свойства переменной) предпочтительнее полагаться на .let
получение неизменяемой ссылки на текущее значение, т.е.
testVar?.let { capturedTestVar ->
println(capturedTestVar.length)
}
Комментарии:
1.На самом деле существует множество встроенных функций определения области видимости, которые пригодятся в зависимости от контекста :
let
run
also
apply
.