ПрограммированиеKotlin разработчик

Объясните особенности работы с Nullable-типами в Kotlin. Какие инструменты языка позволяют безопасно работать с null-значениями? Приведите пример кода и опишите лучшие практики.

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Kotlin реализует безопасную работу с null за счёт системы типов: любой тип по умолчанию не может быть null, например, val a: String = null вызовет ошибку компиляции. Для обозначения возможности присвоить null используется символ вопроса ?, например:

val name: String? = null

Для работы с Nullable-типами предоставляются:

  • Safe-call operator: ?., который возвращает null, если объект сам null, и вызывает метод/поле в противном случае: name?.length.
  • Elvis-operator: ?:, чтобы задать значение по умолчанию, если слева — null: val length = name?.length ?: 0
  • Проверка через if/when: Пример:
if (name != null) { println(name.length) }
  • Оператор assert ( !! ): Принудительно получить значение, бросая NullPointerException, если объект — null (используется крайне аккуратно):
val length = name!!.length

Лучшие практики: минимизировать Nullable-типы, использовать Safe-call и Elvis оператор, избегать !!, явно моделировать ситуации, когда null допустим.

Вопрос с подвохом.

Можно ли присвоить типу val a: String значение null, и как этого избежать?

Ответ: Нет, по умолчанию в Kotlin типы не могут быть равны null. Чтобы позволить присваивание null, надо явно указать val a: String? = null. Типы без ? всегда non-null.

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В проекте банковского приложения переменная типа User хранила результат поиска клиента. Разработчик определил var user: User, но иногда клиент не находился и сервис возвращал null. Это вызывало NPE и массовые краши.


История

В чат-боте для поддержки использовали !! для доступа к сообщениям пользователя (message!!.text), считая что сообщения всегда приходят. Бот падал на первом же пустом сообщении. Safe-call бы избавил от проблемы.


История

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