Всебічне керівництво з питань нульової безпеки в Котліні

1. Огляд

У цій статті ми розглянемо функції нульової безпеки, вбудовані в мову Kotlin. Kotlin забезпечує всебічну, власну обробку полів, що допускають обнулення - додаткові бібліотеки не потрібні.

2. Залежність Мавена

Для початку вам потрібно додати залежність kotlin-stdlib Maven до вашого pom.xml:

 org.jetbrains.kotlin kotlin-stdlib 1.1.1  

Ви можете знайти останню версію на Maven Central.

3. Нульові та ненульовані посилальні типи

У Котліна є два типи посилань , які інтерпретуються компілятором, щоб дати програмісту інформацію про правильність програми під час компіляції - ті, що мають нульовий характер, і ті, які ні.

За замовчуванням Kotlin припускає, що значення не може бути нульовим :

var a: String = "value" assertEquals(a.length, 5)

Ми не можемо присвоїти нулю посилання a , і якщо ви спробуєте, це призведе до помилки компілятора.

Якщо ми хочемо створити посилання, що допускає нуль, нам потрібно створити додавання знака питання (?) До визначення типу :

var b: String? = "value"

Після цього ми можемо призначити йому null :

b = null

Коли ми хочемо отримати доступ до посилання b , ми повинні явно обробляти нульовий регістр, щоб уникнути помилки компіляції, оскільки Котлін знає, що ця змінна може містити null :

if (b != null) { println(b.length) } else { assertNull(b) }

4. Безпечні дзвінки

Поводження з кожним посиланням, яке можна обнулити, може бути громіздким. На щастя, у Kotlin є синтаксис "безпечних викликів" - цей синтаксис дозволяє програмістам виконувати дію лише тоді, коли конкретне посилання містить ненульове значення .

Давайте визначимо два класи даних, щоб проілюструвати цю особливість:

data class Person(val country: Country?) data class Country(val code: String?)

Зауважте, що поля країни та коду мають посилальний тип, що допускає нульовий статус.

Щоб швидко отримати доступ до цих полів, ми можемо використовувати безпечний синтаксис виклику:

val p: Person? = Person(Country("ENG")) val res = p?.country?.code assertEquals(res, "ENG")

Якщо змінна p містить нуль , синтаксис безпечних викликів поверне нульовий результат:

val p: Person? = Person(Country(null)) val res = p?.country?.code assertNull(res)

4.1. Метод let ()

Щоб виконати дію лише тоді, коли посилання містить ненульове значення, ми можемо використовувати оператор let .

Скажімо, у нас є список значень, і в ньому також є нульове значення:

val firstName = "Tom" val secondName = "Michael" val names: List = listOf(firstName, null, secondName)

Далі ми можемо виконати дію з кожним ненульованим елементом списку імен за допомогою функції let :

var res = listOf() for (item in names) { item?.let { res = res.plus(it) } } assertEquals(2, res.size) assertTrue { res.contains(firstName) } assertTrue { res.contains(secondName) }

4.2. Метод also ()

Якщо ми хочемо застосувати якусь додаткову операцію, наприклад, ввійти в журнал для кожного ненульованого значення, ми можемо використати метод also () і зв’язати його за допомогою let ():

var res = listOf() for (item in names) { item?.let { res = res.plus(it); it } ?.also{it -> println("non nullable value: $it")} }

Він роздрукує кожен елемент, який не є нульовим:

non nullable value: Tom non nullable value: Michael

4.3. Метод run ()

Котлін має метод run () для виконання якоїсь операції над онульованим посиланням. Це дуже схоже на let (), але всередині функції функції, метод Run () працює на цьому посиланні замість параметра функції:

var res = listOf() for (item in names) { item?.run{res = res.plus(this)} }

5. Елвіс Оператор

Іноді, коли у нас є посилання, ми хочемо повернути якесь значення за замовчуванням з операції, якщо посилання містить нуль . Для цього ми можемо використовувати оператор elvis ( ? :) . Це еквівалент orElse / orElseGet із класу Java Optional :

val value: String? = null val res = value?.length ?: -1 assertEquals(res, -1)

Коли посилання на значення містить ненульоване значення, буде викликано довжину методу :

val value: String? = "name" val res = value?.length ?: -1 assertEquals(res, 4)

6. Недійсний небезпечний спосіб отримання

Kotlin also has an unsafe operator to get a value of a nullable field without handling absence logic explicitly, but it should be used very carefully.

The double exclamation mark operator (!!) takes a value from a nullable reference and throws a NullPointerException if it holds null. This is an equivalent of Optional.get() operation:

var b: String? = "value" b = null assertFailsWith { b!! }

If the nullable reference holds a non-nullable value, the action on that value will be executed successfully:

val b: String? = "value" assertEquals(b!!.length, 5)

7. Filtering Null Values From a List

The List class in Kotlin has a utility method filterNotNull() that returns only non-nullable values from a list that holds nullable references:

val list: List = listOf("a", null, "b") val res = list.filterNotNull() assertEquals(res.size, 2) assertTrue { res.contains("a") } assertTrue { res.contains("b") }

Це дуже корисна конструкція, яка укладає логіку, яку нам інакше потрібно було б реалізувати самому.

8. Висновок

У цій статті ми глибоко вивчили нульові особливості безпеки Колтіна. Ми бачили типи посилань, які можуть містити нульові значення, а ті, що не можуть. Ми реалізували вільну логіку обробки нуля , використовуючи функції "безпечного виклику" та оператора elvis .

Реалізацію всіх цих прикладів та фрагментів коду можна знайти у проекті GitHub - це проект Maven, тому його слід легко імпортувати та запускати як є.