Комплексное руководство по нулевой безопасности в Котлине

Всеобъемлющее руководство по нулевой безопасности в Котлине

1. обзор

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

2. Maven Dependency

Для начала вам нужно добавить зависимость Mavenkotlin-stdlib к вашемуpom.xml:


    org.jetbrains.kotlin
    kotlin-stdlib
    1.1.1

Вы можете найти последнюю версию наMaven Central.

3. Обнуляемые и ненулевые ссылочные типы

Kotlin has two types of references, которые интерпретируются компилятором, чтобы предоставить программисту информацию о правильности программы во время компиляции - те, которые допускают значение NULL, и те, которые нет.

По умолчанию Kotlin предполагает, что значение не может бытьnull:

var a: String = "value"

assertEquals(a.length, 5)

Мы не можем присвоитьnull ссылкеa, и если вы попытаетесь это сделать, это вызовет ошибку компилятора.

If we want to create a nullable reference, we need to create append the question mark(?) to the type definition:

var b: String? = "value"

После этого мы можем присвоить емуnull:

b = null

When we want to access the b reference, we must handle the null case explicitly, чтобы избежать ошибки компиляции, потому что Kotlin знает, что эта переменная может содержатьnull:

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

4. Безопасные звонки

Таким образом, обработка каждой недействительной ссылки может быть обременительной. К счастью, в Kotlin есть синтаксис для «безопасных вызовов» - этот синтаксис позволяет программистам использоватьexecute an action only when the specific reference holds a non-null value.

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

data class Person(val country: Country?)

data class Country(val code: String?)

Обратите внимание, что поляcountry иcode имеют ссылочный тип, допускающий значение NULL.

Для быстрого доступа к этим полям мы можем использовать синтаксис безопасного вызова:

val p: Person? = Person(Country("ENG"))

val res = p?.country?.code

assertEquals(res, "ENG")

Если переменнаяp содержитnull, синтаксис безопасных вызовов вернет результатnull:

val p: Person? = Person(Country(null))

val res = p?.country?.code

assertNull(res)

4.1. Метод Let ()

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

Допустим, у нас есть список значений, и в нем также есть значениеnull:

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

Затем мы можем выполнить действие для каждого не обнуляемого элемента спискаnames, используя функцию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. Метод также ()

Если нам нужен методto apply some additional operation, for example logging on every non-nullable value we can use analso() и связать его с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 ()

В Kotlin есть методrun() для выполнения некоторой операции над ссылкой, допускающей значение NULL. Он очень похож наlet(), но внутри тела функции - метод Run () operates on this reference instead of a function parameter:

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

5. Элвис Оператор

Иногда, когда у нас есть ссылка, мы хотим вернуть некоторое значение по умолчанию из операции, если ссылка содержитnull. Для этого мы можем использовать операторelvis (?:). Это эквивалентorElse/orElseGet из класса JavaOptional:

val value: String? = null

val res = value?.length ?: -1

assertEquals(res, -1)

Когда ссылкаvalue содержит значение, не допускающее значения NULL, будет вызван методlength:

val value: String? = "name"

val res = value?.length ?: -1

assertEquals(res, 4)

6. Nullable Unsafe Get

В Kotlin также есть небезопасный оператор для получения значения поля, допускающего значение NULL, без явной обработки логики отсутствия, но его следует использовать очень осторожно.

Оператор двойного восклицательного знака (!!) принимает значение из ссылки, допускающей значение NULL, и выдаетNullPointerException, если он содержитnull.. Это эквивалент операцииOptional.get():

var b: String? = "value"
b = null

assertFailsWith {
    b!!.length
}

Если ссылка, допускающая обнуляемость, содержит ненулевое значение, действие над этим значением будет выполнено успешно:

val b: String? = "value"

assertEquals(b!!.length, 5)

7. Фильтрация нулевых значений из списка

КлассList в Kotlin имеет служебный методfilterNotNull(), который возвращает только значения, не допускающие значения NULL, из списка, содержащего ссылки, допускающие значение NULL:

val list: List = listOf("a", null, "b")

val res = list.filterNotNull()

assertEquals(res.size, 2)
assertTrue { res.contains("a") }
assertTrue { res.contains("b") }

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

8. Заключение

В этой статье мы подробно изучили нулевые функции безопасности Koltin. Мы видели типы ссылок, которые могут содержать значенияnull, и те, которые не могут. Мы реализовали свободную логику обработкиnull, используя функции «безопасного вызова» и операторelvis.

Реализация всех этих примеров и фрагментов кода можно найти вGitHub project - это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.