Gradle JVM兼容性:如何让Kotlin 1.8与Java 11协同工作

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么你的Kotlin和Java项目会突然“崩溃”?

\n\n

你是否遇到过这样的情况:用Kotlin编写代码,使用Java 11作为主要代码,而Gradle突然报出兼容性错误?熟悉吗?这是配置多模块项目时最常见的问题之一。尤其是当你使用build.gradle.kts(Kotlin DSL)并试图让compileJava与compileKotlin协同工作时。在本文中,我们将详细讲解如何正确设置JVM目标兼容性,使你的项目能够无错误地构建。没错,我们将用中文、幽默且不枯燥的方式来完成。

\n\n

如果你是从Stack Overflow过来的,那么你知道原始问题已经获得了数千次浏览。我们将其改编为教育性内容,让你不仅仅是复制答案,而是理解错误产生的原因以及如何在未来避免它。

\n\n

问题:当Java和Kotlin说不同的语言时

\n\n

想象一下,Java 11是一位严格的教授,要求一切都符合标准。而Kotlin 1.8则是一位富有创造力的同事,想要使用新功能,但忘记通知教授。结果就是——冲突。

\n\n

在Gradle中,每个编译任务(compileJava、compileKotlin)都有自己的JVM目标——代码编译成的字节码版本。如果它们不匹配,你会得到类似这样的错误:

\n\n
Error: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.\n
\n\n

或者更糟的是——由于字节码不兼容而导致性能无声下降。

\n\n

为什么这恰恰发生在build.gradle.kts中?

\n\n

Kotlin DSL(.gradle.kts文件)是一个强大的工具,但它需要显式指定参数。与Groovy DSL不同,后者某些设置会自动“捕获”,而在Kotlin DSL中,你必须精确。特别是关于JVM目标的设置。

\n\n

典型错误:你设置了java.targetCompatibility = JavaVersion.VERSION_11,但忘记为Kotlin指定相同的设置。或者反过来——配置了compileKotlin,而compileJava仍然停留在Java 8上。

\n\n

正确的解决方案:为Java和Kotlin设置统一的JVM目标

\n\n

为了避免错误,需要为两个任务显式设置JVM目标。以下是在build.gradle.kts中的操作方法:

\n\n

步骤1. 配置Java(compileJava)

\n\n

在java {}块或tasks.withType<JavaCompile>()中添加:

\n\n
java {\n    sourceCompatibility = JavaVersion.VERSION_11\n    targetCompatibility = JavaVersion.VERSION_11\n}\n\ntasks.withType<JavaCompile>() {\n    options.encoding = "UTF-8"\n    options.compilerArgs.add("-parameters")\n}\n
\n\n

请注意:sourceCompatibility和targetCompatibility必须相同。如果你用Java 11编写代码,那么字节码也应该是Java 11。

\n\n

步骤2. 配置Kotlin(compileKotlin)

\n\n

现在最重要的是——为Kotlin设置JVM目标。这可以通过kotlin {}块或tasks.withType<KotlinCompile>()来完成:

\n\n
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\ntasks.withType<KotlinCompile>() {\n    kotlinOptions {\n        jvmTarget = "11"  // 注意:这是字符串,而不是JavaVersion!\n        apiVersion = "1.8"\n        languageVersion = "1.8"\n    }\n}\n
\n\n

为什么jvmTarget是字符串?因为Kotlin期望的是版本的字符串表示形式(例如,"1.8"、"11"、"17")。如果你尝试传递JavaVersion.VERSION_11,编译器会报错。

\n\n

完整的build.gr

博客

书籍推荐