Null на границе Kotlin и Java
Вопрос
Как Kotlin обеспечивает null-safety, если код вызывают из Java или Kotlin вызывает Java?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Из Java в Kotlin: проверки параметров `checkNotNullParameter` в публичных функциях
Из Kotlin в Java: платформенные типы без проверки компилятора
Аннотации nullability делают типы нормальными
Присваивание платформенного типа в non-null вставляет проверку на месте
Рефлексия и сериализация могут положить null в non-null поле
Что могут спросить следом
- Где ещё рефлексия ломает null-safety?
- Можно ли отключить проверки параметров?
Разбор
Kotlin защищает обе стороны границы, но по-разному. Если Java вызывает публичную Kotlin-функцию с non-null параметром и передаёт null, функция упадёт сразу на входе: компилятор вставляет вызов Intrinsics.checkNotNullParameter с именем параметра в сообщении. Если Kotlin вызывает Java-метод без аннотаций, результат имеет платформенный тип, и компилятор не требует проверок. Когда такой результат присваивают в переменную non-null типа, вставляется проверка, и NPE случится прямо в этом месте, а если тип не указан, ошибка может уехать дальше по коду. Аннотации @Nullable и @NonNull превращают платформенные типы в обычные. Отдельная дыра это рефлексия: Gson создаёт объекты в обход конструктора и может положить null в поле типа String, поэтому для Kotlin лучше kotlinx.serialization или Moshi с кодогенерацией.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.