当项目的gradle升级到8.0之后,由于项目中使用了room,因此也使用了ksp替代kapt,然后我在编译的过程中就遇到了如下错误
Caused by: org.gradle.api.GradleException: 'compileDebugJavaWithJavac' task (current target is 1.8) and 'kspDebugKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version.
google一番,找到了几个比较相关的解释
- https://stackoverflow.com/questions/69079963/how-to-set-compilejava-task-11-and-compilekotlin-task-1-8-jvm-target-com
- https://stackoverflow.com/questions/52492459/how-does-sourcecompatibility-and-targetcompatibility-impact-number-of-supported
解决方案也很简单,把项目中的这几个版本都指定为一致就行
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
那么问题又来了,java版本设置得如此高,为什么能够在设备上正常运行,没有崩溃?
android在编译kotlin和java的代码过程中,经历过如下几个步骤
源码 → 字节码 → 字节码脱糖 → dex
编译器后端会根据我们指定的minSdkVersion来决定目标字节码版本(不同版本的安卓系统支持的jdk不同)
根据官方文档对jdk版本的说明,当编译sdk版本指定为34之后,我们就可以使用部分jdk 17的api
再次澄清几个jdk使用的不同的地方的概念
AGP插件运行在Gradle中,Gradle的jdk版本则是AGP插件运行的版本,通常来说,Gradle的jdk版本可以比AGP插件要求的jdk版本高,
sourceCompatibility指定了在源代码中可以使用的java sdk api的版本,如果没有指定sourceCompatibility,那么在源代码中可以使用的jdk版本由指定的java 工具链版本或者运行Gradle的jdk版本,sourceCompatibility低于targetCompatibility,targetCompatibility和jvmTarget指定了字节码的版本
因此总结来说,你当然可以使用高版本的Java的api,前提是你的工具链支持这些特点
为了保持本地编译环境和远程ci编译环境的结果的一致性,最好指定sourceCompatibility等字段