Kotlin
Нулевая безопасность
Поиск…
Nullable и Non-Nullable типы
Обычные типы, такие как String
, не имеют значения NULL. Чтобы сделать их способными удерживать нулевые значения, вы должны явно обозначить, что, поставив a ?
за ними: String?
var string : String = "Hello World!" var nullableString: String? = null string = nullableString // Compiler error: Can't assign nullable to non-nullable type. nullableString = string // This will work however!
Оператор безопасного вызова
Для доступа к функциям и свойствам типов с нулевым значением вам необходимо использовать специальные операторы.
Первый, ?.
, дает вам свойство или функцию, к которой вы пытаетесь получить доступ, или дает null, если объект имеет значение null:
val string: String? = "Hello World!" print(string.length) // Compile error: Can't directly access property of nullable type. print(string?.length) // Will print the string's length, or "null" if the string is null.
Идиома: вызов нескольких методов на одном и том же объекте с нулевой отметкой
Элегантный способ назвать несколько методов нулевой проверкой объекта с использованием Котлин - х apply
так:
obj?.apply {
foo()
bar()
}
Это вызовет foo
и bar
на obj
( this
в блоке apply
), только если obj
является нулевым, в противном случае пропускает весь блок.
Чтобы принести переменную с нулевым значением в область видимости как ссылку, не содержащую нулевых значений, не делая ее неявным приемом вызовов функций и свойств, вы можете использовать let
вместо apply
:
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull
можно было бы назвать что - нибудь, или даже оставил, и использовать через неявного параметра лямбда it
.
Смарт-броски
Если компилятор может сделать вывод о том, что объект не может иметь значение null в определенный момент, вам больше не нужно использовать специальные операторы:
var string: String? = "Hello!"
print(string.length) // Compile error
if(string != null) {
// The compiler now knows that string can't be null
print(string.length) // It works now!
}
Примечание . Компилятор не позволит вам использовать измененные переменные, которые могут быть изменены между нулевой проверкой и предполагаемым использованием.
Если переменная доступна из-за пределов области текущего блока (например, они являются членами нелокального объекта), вам нужно создать новую локальную ссылку, которую затем вы сможете использовать и использовать.
Устранение нулей из Iterable и массива
Иногда нам нужно изменить тип из Collection<T?>
Collections<T>
. В этом случае filterNotNull
является нашим решением.
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Null Coalescing / Elvis Operator
Иногда желательно оценивать значение NULL в стиле if-else. Оператор Элвиса, ?:
, Может быть использован в Котлине для такой ситуации.
Например:
val value: String = data?.first() ?: "Nothing here."
Вышеприведенное выражение возвращает "Nothing here"
если data?.first()
или сами data
дают null
значение иначе результат data?.first()
.
Кроме того, можно исключить исключения, используя тот же синтаксис, чтобы прервать выполнение кода.
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
Напоминание: NullPointerExceptions могут быть выбрасываться с помощью оператора утверждения (например,
data!!.second()!!
)
Утверждение
!!
суффиксы игнорируют значение nullability и возвращают ненулевую версию этого типа. KotlinNullPointerException
будет KotlinNullPointerException
, если объект является null
.
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
Оператор Элвиса (? :)
В Kotlin мы можем объявить переменную, которая может содержать null reference
. Предположим, что мы имеем нулевую ссылку a
, мы можем сказать: «если a
не является нулевым, используйте его, в противном случае используйте некоторое ненулевое значение x
»
var a: String? = "Nullable String Value"
Теперь a
может быть нулевым. Поэтому, когда нам нужно получить доступ к значению a
, нам нужно выполнить проверку безопасности, независимо от того, содержит ли она значение или нет. Мы можем выполнить эту проверку безопасности с помощью обычного выражения if...else
.
val b: Int = if (a != null) a.length else -1
Но здесь идет вперед оператор Elvis
(Elvis Оператор: ?:
). Выше, if...else
может быть выражено с помощью оператора Элвиса, как показано ниже:
val b = a?.length ?: -1
Если выражение слева от ?:
(Здесь: a?.length
) не равно null, оператор elvis возвращает его, иначе он возвращает выражение вправо (здесь: -1
). Выражение правой стороны оценивается только в том случае, если левая сторона равна нулю.