За счет чего достигается null-safety в Kotlin и почему Kotlin — null-safe язык, а Java — нет
Что проверяют
Понимаете ли вы, что null-safety в Kotlin встроена в систему типов и проверяется компилятором, а не держится на дисциплине. Следом почти всегда спрашивают, где в Kotlin всё-таки можно получить NullPointerException.
Как отвечать
В Kotlin nullability это часть типа. String и String? разные типы: в первый нельзя присвоить null, у второго нельзя вызвать метод без проверки. Ошибка ловится при компиляции. Инструменты для nullable:
?.: безопасный вызов, приnullвся цепочка даётnull;?:: оператор Элвиса, значение по умолчанию или ранний выход:val id = arguments?.getString("id") ?: return;- smart cast: после
if (x != null)компилятор сам считаетxненулевым. Работает дляvalи локальных переменных, но не для изменяемого свойства класса, которое могло поменяться между проверкой и использованием; !!: явное «я уверен», приnullбросает NPE.
В Java любая ссылка может быть null, и компилятор это не отслеживает. Аннотации @Nullable и @NonNull читают IDE и анализаторы вроде NullAway, но javac их не проверяет. Optional задуман для возвращаемых значений и от null в полях и параметрах не спасает.
Сильная часть ответа это границы гарантий. Значения из Java приходят в Kotlin как платформенные типы (String!): компилятор не знает, бывает ли там null, и не мешает вызвать метод. Если Java-код размечен аннотациями, Kotlin их учитывает. На публичных функциях Kotlin вставляет проверки параметров, поэтому null из Java падает сразу на входе, а не в глубине кода.
Где спотыкаются
Говорят, что в Kotlin NPE невозможен. Он возможен через !!, платформенные типы, Java-библиотеки и обращение к свойству из конструктора базового класса до его инициализации.
Не знают про Gson. Он создаёт объекты в обход конструктора и спокойно кладёт null в поле типа String, а падение случается позже, при обращении. Для Kotlin надёжнее kotlinx.serialization или Moshi с кодогенерацией.
Путают lateinit с null-safety. Обращение до инициализации бросает UninitializedPropertyAccessException, это та же ошибка времени выполнения под другим именем.