Как настроить interoperability между Kotlin и Java в Gradle?
Интероперабельность (interoperability) между Kotlin и Java в Gradle-проекте — это возможность свободного взаимодействия кода на Kotlin и Java в одном Android или JVM проекте. Это одна из главных причин, по которой Kotlin так легко внедряется в существующие Java-кодовые базы. Kotlin специально проектировался с высокой совместимостью с Java и их экосистемами, включая инструменты сборки, такие как Gradle.
1. Совместное использование исходных файлов Java и Kotlin
Для начала в проекте должны присутствовать как Java, так и Kotlin исходники. Стандартная структура проекта может выглядеть так:
src/
├── main/
│ ├── java/ → Java-файлы
│ └── kotlin/ → Kotlin-файлы
Gradle умеет компилировать Java и Kotlin в нужной последовательности. Kotlin компилируется после Java, чтобы видеть классы, скомпилированные на Java.
2. Подключение Kotlin плагина в build.gradle.kts (или build.gradle)
В build.gradle.kts (Kotlin DSL):
plugins {
kotlin("jvm") version "1.9.0" // или kotlin("android") для Android-проекта
}
Или в build.gradle (Groovy DSL):
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.9.0'
}
3. Указание исходных директорий
Gradle автоматически включает директории src/main/kotlin и src/main/java. Однако, если вы используете нестандартную структуру, нужно указать пути вручную:
sourceSets {
main {
java.srcDirs("src/main/java", "src/main/kotlin")
}
}
4. Настройка зависимостей Kotlin
В секции зависимостей:
dependencies {
implementation(kotlin("stdlib")) // или stdlib-jdk8 для JDK 8+
}
Для Android-проектов:
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
}
5. Настройка kotlinOptions
Добавьте:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8" // или "11" или выше
}
}
Это нужно для корректной компиляции Kotlin в байткод совместимый с JVM версии 8 и выше, и для его корректной работы с Java-кодом.
6. Использование аннотаций для совместимости
Иногда Kotlin-функции или свойства нужно делать совместимыми с Java. Для этого используются аннотации:
-
@JvmStatic — чтобы сделать метод статическим в Java.
-
@JvmOverloads — для генерации перегруженных методов.
-
@JvmField — чтобы обратиться к полю без геттеров/сеттеров.
-
@file:JvmName("MyUtils") — чтобы задать имя класса для file-level функций.
7. Java-код вызывает Kotlin
Java может напрямую обращаться к Kotlin-классам, функциям и свойствам, как если бы они были написаны на Java. Однако есть нюансы:
-
У Kotlin-свойств нет стандартных setField() — нужны getX() / setX() методы.
-
В Java нужно использовать .INSTANCE для обращения к объекту object.
-
Companion-объекты в Kotlin из Java вызываются через MyClass.Companion.method() (или @JvmStatic, чтобы это упростить).
8. Kotlin вызывает Java
Здесь ограничений почти нет. Kotlin может:
-
Наследовать Java-классы
-
Вызывать методы, конструкторы, поля
-
Работать с аннотациями и лямбдами
-
Использовать SAM-конверсии (Single Abstract Method)
9. Настройка Kotlin и Java в settings.gradle или multi-module проектах
Если проект состоит из нескольких модулей, каждый из которых использует Kotlin и Java, следует в каждом модуле подключить Kotlin плагин, и убедиться, что kotlin("stdlib") и kotlinOptions.jvmTarget заданы везде.
Пример:
allprojects {
repositories {
google()
mavenCentral()
}
}
subprojects {
plugins.withId("org.jetbrains.kotlin.jvm") {
dependencies {
"implementation"(kotlin("stdlib"))
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
}
}
10. Пример простого проекта с Kotlin и Java
fun main() {
val greeter = Greeter()
greeter.sayHello("Kotlin")
}
Greeter.java
public class Greeter {
public void sayHello(String name) {
System.out.println("Hello, " + name + " from Java!");
}
}
Gradle соберёт оба файла и запустит программу без проблем.