Как компилируется Kotlin: в Java байткод или напрямую
Что проверяют
Понимаете ли вы, как Kotlin уживается с Java в одном проекте и почему его классы видны из Java без обёрток. Следом обычно спрашивают, как Java-код вызывает top-level функции Kotlin и откуда в байткоде берутся проверки на null.
Как отвечать
Короткий ответ: Kotlin/JVM компилируется в байткод JVM напрямую. Промежуточного Java-кода нет, компилятор kotlinc сам выпускает файлы .class, и для JVM они ничем не отличаются от собранных javac. Поэтому точнее говорить «байткод JVM», а не «Java-байткод».
Дальше покажите, что знаете детали:
- другие цели: Kotlin/Native собирает нативные бинарники через LLVM без JVM, есть также Kotlin/JS и Kotlin/Wasm. Байткод это только одна из платформ;
- смешанный проект: сначала работает компилятор Kotlin, он читает объявления из
.javaисходников, чтобы разрешить ссылки. Потомjavacкомпилирует Java, уже видя готовые Kotlin-классы; - что генерируется: top-level функции из
Utils.ktпопадают в классUtilsKtсо статическими методами, свойства превращаются в геттеры и сеттеры,data classполучаетequals,hashCode,toString,copy; - аннотации для Java:
@JvmStatic,@JvmOverloads,@JvmField,@JvmNameменяют то, как код выглядит со стороны Java; - null-безопасность: в байткоде это аннотации
@NotNullи@Nullableплюс проверки параметров публичных методов черезkotlin.jvm.internal.Intrinsics. Java может передатьnull, и исключение вылетит на входе в метод, а не глубже; - корутины:
suspend-функция получает скрытый параметрContinuation, а тело превращается в конечный автомат.
В рантайме приложению нужен kotlin-stdlib. Посмотреть байткод можно прямо в IntelliJ IDEA: Show Kotlin Bytecode и затем Decompile.
Где спотыкаются
Говорят, что Kotlin сначала переводится в Java, а потом компилируется. Этого шага нет, декомпилированный Java-код в IDE это лишь способ прочитать байткод.
Считают, что null-безопасность работает и на стыке с Java. Значения из Java приходят с платформенным типом String!, и компилятор не заставит их проверять.
Забывают, что Kotlin умеет не только JVM, и на вопрос «или напрямую» отвечают «только байткод», упуская Kotlin/Native.