Kotlin как клей: Интеграция с Java, Python, C и JS

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Kotlin не живёт в вакууме: зачем и как дружить с другими языками

Представьте: вы пишете на Kotlin — современном, лаконичном и безопасном языке. Но ваш проект — это не чистый лист. Где-то в недрах системы живёт legacy-код на Java, аналитикам нужна библиотека на Python, а для низкоуровневых операций требуется C. Или вы хотите переиспользовать бизнес-логику на фронтенде, написав её на Kotlin, но там правит бал JavaScript.

Хорошая новость: интеграция Kotlin с другими языками — это не боль, а суперсила. Kotlin спроектирован так, чтобы быть «языком-клеем». Он умеет работать на JVM (рядом с Java), компилироваться в нативный код (Kotlin/Native) и даже в JavaScript (Kotlin/JS).

В этой статье мы разберём четыре ключевых сценария взаимодействия Kotlin с другими языками на практических примерах. Вы узнаете, как вызывать Python из Kotlin, встраивать C-код через JNI, бесшовно работать с Java и даже использовать Kotlin на фронтенде. Поехали!

1. Kotlin и Java: родственная душа с первых строк

Самый очевидный и простой сценарий — Kotlin Java взаимодействие. Поскольку Kotlin компилируется в байт-код JVM, он на 100% совместим с Java. Вы можете вызывать любой Java-код из Kotlin и наоборот — без мостов, адаптеров и боли.

Как вызвать Java из Kotlin

Допустим, у вас есть старый Java-класс для работы с датами:

// Java: DateUtils.java
public class DateUtils {
    public static String formatDate(long timestamp) {
        return new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date(timestamp));
    }
}

В Kotlin вы используете его как родной:

// Kotlin
fun main() {
    val formatted = DateUtils.formatDate(System.currentTimeMillis())
    println("Сегодня: $formatted") // Сегодня: 2025-04-03
}

Всё работает «из коробки». Но есть нюансы: null-безопасность. Java не знает про nullable-типы Kotlin, поэтому при вызове Java-методов Kotlin трактует возвращаемые значения как платформенные типы (например, String!). Совет: всегда явно указывайте тип или используйте !! / ?. с умом.

Как вызвать Kotlin из Java

Обратная совместимость тоже есть. Предположим, у вас есть Kotlin-файл:

// Kotlin: Calculator.kt
package utils

object Calculator {
    @JvmStatic
    fun sum(a: Int, b: Int): Int = a + b
}

Из Java вызываем так:

// Java
import utils.Calculator;

public class Main {
    public static void main(String[] args) {
        int result = Calculator.sum(5, 3);
        System.out.println(result); // 8
    }
}

Главное — не забыть аннотацию @JvmStatic для статических методов и @JvmName для разрешения конфликтов имён. Интеграция Kotlin с Java настолько плотная, что вы можете смешивать оба языка в одном проекте — это стандарт для Android-разработки и многих бэкендов на Spring.

2. Kotlin и Python: два мира, одна JVM (и GraalVM)

А вот это уже интереснее. Kotlin Python — не самая тривиальная связка, но она возможна. Прямого нативного моста нет, но мы можем использовать JVM-решения.

Вариант A: GraalVM — запускаем Python на JVM

GraalVM — это виртуальная машина, которая умеет запускать несколько языков (Java, Kotlin, JavaScript, Python, Ruby) в одном процессе. Это идеальный инструмент для интеграции Kotlin с Python.

Установите GraalVM и добавьте поддержку Python:

gu install python

Теперь в Kotlin-коде можно вызывать Python-функции:

// Kotlin (GraalVM Polyglot API)
import org.graalvm.polyglot.*

fun main() {
    val context = Context.create("python")
    // Выполняем Python-код
    context.eval("python", """
        import math
        def calculate_hypotenuse(a, b):
            return math.sqrt(a*a + b*b)
    """.trimIndent())

    // Вызываем функцию из Kotlin
    val result = context.getBindings("python")
        .getMember("calculate_hypotenuse")
        .execute(3, 4)
        .asInt()

    println("Гипотенуза: $result") // 5
}

Это мощно: вы можете использовать любую Python-библиотеку (например, NumPy или Pandas) прямо из Kotlin. Минус — GraalVM не всегда стабильна с Python, и производительность может быть ниже, чем у родного CPython.

Вариант B: Вызов Python через системный процесс

Простой, но надёжный способ — запустить Python-скрипт как внешний процесс и обменяться данными через JSON или stdin/stdout:

// Kotlin: запускаем Python и получаем результат
import java.io.File

fun callPythonScript(scriptPath: String, input: String): String {
    val process = ProcessBuilder("python3", scriptPath)
        .redirectErrorStream(true)
        .start()

    process.outputStream.bufferedWriter().use { writer ->
        writer.write(input)
        writer.flush()
    }

    return process.inputStream.bufferedReader().readText()
}

fun main() {
    val result = callPythonScript("analyze.py", "Kotlin is awesome!")
    println("Python сказал: $result")
}

Этот подход универсален и не требует дополнительных инструментов. Вызов Python из Kotlin через подпроцессы — хороший выбор для микросервисной архитектуры.

3. Kotlin и C/C++: уходим в низкоуровневый код через JNI

Когда нужна работа с железом, графикой или legacy-библиотеками на C, на помощь приходит Kotlin C JNI. JNI (Java Native Interface) — стандартный механизм для вызова нативного кода из JVM. Kotlin здесь ничем не отличается от Java.

Пример: вызываем функцию на C из Kotlin

Сначала пишем C-код:

// native.c
#include <jni.h>
#include <stdio.h>

JNIEXPORT jstring JNICALL
Java_com_example_NativeLib_sayHello(JNIEnv *env, jobject obj, jstring name) {
    const char *nativeName = (*env)->GetStringUTFChars(env, name, 0);
    char buffer[256];
    sprintf(buffer, "Привет, %s! Я C-код.", nativeName);
    (*env)->ReleaseStringUTFChars(env, name, nativeName);
    return (*env)->NewStringUTF(env, buffer);
}

Компилируем в динамическую библиотеку:

gcc -shared -fpic -o libnative.so -I"$JAVA                

Блоги

Рекомендаций по книгам