← Назад к списку
ТехническаяJava и KotlinJunior

Как Kotlin решает проблему NullPointerException и что происходит на границе с Java-кодом?

Короткий ответ

  • Nullable и non-null типы различаются на уровне системы типов: String и String?
  • К nullable нельзя обратиться без проверки — компилятор не даст
  • Операторы: ?. безопасный вызов, ?: элвис, !! осознанный риск
  • let, smart cast после проверки if (x != null)
  • Типы из Java без аннотаций — платформенные (String!), проверки нет
  • Аннотации @Nullable/@NotNull в Java-коде делают границу безопасной

Kotlin выносит nullability в систему типов, а риски остаются на границе с Java через платформенные типы.

Как сказать вслух

пример ответа

В Котлине возможность null — часть типа: строка без знака вопроса не может быть null в принципе, а со знаком — может, и компилятор заставит это обработать. Для работы с nullable есть безопасный вызов через ?., элвис-оператор для значения по умолчанию, и !!, который бросит исключение, если там всё-таки null. Опасное место — вызовы Java-кода: там типы платформенные, компилятор ничего не гарантирует, поэтому в Java-коде стоит расставлять аннотации nullability.

Подробный ответ

Основной ответ

Система типов Kotlin разделяет T и T?: присвоить null в String нельзя, а к String? нельзя обратиться без обработки. Инструменты: safe call a?.b (вернёт null, если a == null), элвис a ?: default, безопасное приведение as?, функции области видимости (let для «если не null»), smart cast — после проверки if (a != null) компилятор сам сужает тип. Оператор !! принудительно разыменовывает и бросает NullPointerException — его используют осознанно и редко. Коллекции тоже типизированы: List<String> vs List<String?>. Граница с Java: типы без аннотаций приходят как платформенные (обозначаются String!), и компилятор доверяет разработчику — NPE возможен в рантайме. Аннотации JSR-305/JetBrains (@Nullable, @NotNull) в Java-коде превращают платформенные типы в честные nullable/non-null. lateinit var — для внедрения зависимостей, бросает понятную ошибку при раннем доступе.

Ключевые моменты

  • Типы, а не проверки. Nullability — часть сигнатуры; ошибка ловится компиляцией, а не в проде.
  • Операторы. ?. и ?: покрывают большинство случаев; !! — красный флаг на код-ревью без обоснования.
  • Платформенные типы. Java без аннотаций — зона без гарантий; NPE из Java-вызова остаётся возможным.
  • Smart cast. Работает для val и локальных переменных; для изменяемых свойств нужен let или локальная копия.

Практический контекст

В смешанных Java/Kotlin-проектах (типичный бэкенд на Spring) главные NPE живут на границе: Java-метод вернул null там, где Kotlin ждал non-null. Поэтому команды аннотируют Java-API и включают строгий режим JSR-305. Интервьюер проверяет не перечисление операторов, а понимание платформенных типов и привычку избегать !!. Плюсом будет упомянуть, что data-классы и дефолтные значения параметров тоже снижают число null-полей.

Частые ошибки

  • Злоупотребляют !! вместо нормальной обработки nullable
  • Считают, что Kotlin полностью исключает NPE, забывая про Java-interop и lateinit
  • Не знают, что smart cast не работает с изменяемыми свойствами класса

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru