На этом шаге мы в общем рассмотрим механизм поддержки в отношении null.
Kotlin имеет строгие правила в отношении null по сравнению с другими языками, такими как Java. Это исключительно особенность Kotlin, но давайте посмотрим, как реализованы эти правила. Защищают ли правила языка Kotlin, когда вы взаимодействуете с менее строгими языками, такими как Java? Вспомните функцию printPlayerStatus из 35 шага:
. . . . private fun printPlayerStatus(auraColor: String, isBlessed: Boolean, name: String, healthStatus: String) { println("(Aura: $auraColor) " + "(Blessed: ${if (isBlessed) "YES" else "NO"})") println("$name $healthStatus") } . . . .
В Kotlin сигнатура функции очевидна - аргументы auraColor, name, healthStatus должны иметь тип String, без поддержки null, а аргумент isBlessed должен иметь тип Boolean, тоже не поддерживающий null. Однако в Java действуют иные правила для работы с null, в Java String вполне может быть null.
Как Kotlin поддерживает null-безопасное окружение? Ответ на этот вопрос потребует погружения в скомпилированный байт-код Java:
public static final void printPlayerStatus(@NotNull String auraColor, boolean isBlessed, @NotNull String name, @NotNull String healthStatus) { Intrinsics.checkParameterIsNotNull(auraColor, "auraColor"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(healthStatus, "healthStatus"); . . . . }
Есть два механизма, гарантирующих, что в параметры без поддержки null не получится передать аргументы со значением null. Во-первых, обратите внимание на аннотации @NonNull рядом с каждым параметром не простого типа в printPlayerStatus. Эти аннотации служат сигналом для кода, вызывающего этот Java-метод, что аннотированные параметры не принимают значение null. isBlessed не требует аннотации @NotNull, так как в Java булевы значения представлены простым типом и как таковые не могут иметь значение null.
Аннотации @NotNull можно увидеть во многих Java-проектах, но они особенно полезны для тех, кто вызывает методы Java из Kotlin, потому что компилятор последнего использует их , чтобы определить, поддерживает ли параметр метода Java значение null.
Компилятор Kotlin делает еще один шаг, чтобы гарантировать, что auraColor, name, healthStatus не получат значение null: он использует метод Intrinsics.checkParameterlsNotNull. Этот метод вызывается для каждого параметра, не поддерживающего null, и возбуждает исключение IllegalArgumentException, если попытаться передать в аргументе значение null.
Проще говоря, любая функция, объявленная в Kotlin, будет играть по правилам Kotlin в отношении null, даже после трансляции в Java-код для JVM.
Итак, Kotlin обеспечивает двойную защиту от NullPointerException ваших функций, которые имеют параметры с типами без поддержки null, даже когда дело доходит до совместной работы с языками, менее строгими в отношении null.
Со следующего шага мы начнем рассматривать работу со строками.