3 月 3 日,JetBrains 发布了 Kotlin 2.3.20-RC2。这个版本虽然是增量更新,但带来了几个非常实用的改进——尤其是对 JPA 开发者和 Kotlin/Native 用户来说,值得关注。
本文带你快速过一遍这次更新的核心内容。
1. JPA 插件重大升级:自动 all-open
这可能是本次更新中最实用的改动。
用过 Spring + Kotlin 的开发者一定踩过这个坑:Kotlin 的 class 默认是 final 的,而 JPA / Hibernate 需要实体类是 open 的,才能正确生成代理对象。以前你必须手动配置 all-open 插件,或者在每个实体类上加 open 关键字。
现在,kotlin.plugin.jpa 插件会自动帮你搞定这一切:
- 自动应用
all-open编译器插件 - 内置 JPA 预设,自动识别以下注解并将类标记为
open:javax.persistence.Entityjavax.persistence.Embeddablejavax.persistence.MappedSuperclassjakarta.persistence.Entity(Jakarta 命名空间同样支持)
也就是说,你只需要引入 JPA 插件,就同时获得了 no-arg 构造函数和 all-open 行为,不再需要额外配置。
对于 Maven 用户,kotlin-maven-noarg 依赖现在也会隐式包含 kotlin-maven-allopen,同样开箱即用。
一个看似小的改动,能省掉多少 StackOverflow 搜索和排查时间,只有踩过坑的人知道。
2. Lombok 插件升级至 Alpha
Kotlin 的 Lombok 编译器插件从实验阶段提升到了 Alpha 状态。
这个插件最早在 Kotlin 1.5.20 引入,目的是让 Kotlin 代码能够直接使用 Java 中 Lombok 生成的声明(getter/setter/builder 等),方便在 Kotlin/Java 混编模块中工作。
虽然仍处于早期阶段,但 Alpha 意味着 JetBrains 已经将其纳入正式产品化路线。如果你的项目还在从 Java 向 Kotlin 迁移,且大量依赖 Lombok,这是个好消息。
3. Kotlin/Native:新的 C/ObjC 互操作模式
Kotlin/Native 引入了一个新的实验性互操作模式,用于解决导入 C 和 Objective-C 库时的 KMP 兼容性问题。
启用方式:
kotlin {
targets.withType<KotlinNativeTarget>().configureEach {
compilations.configureEach {
cinterops.configureEach {
extraOpts += listOf("-Xccall-mode", "direct")
}
}
}
}
需要注意的是,这个功能还处于实验阶段,暂时不要用它发布库。JetBrains 正在通过 YouTrack (KT-83218) 收集反馈。
4. Gradle 9.3.0 支持 & BTA 默认启用
两个构建相关的更新:
Gradle 兼容性扩展:现在完全兼容 Gradle 7.6.3 到 9.3.0 的所有版本。
Kotlin/JVM 编译默认使用 Build Tools API (BTA):这是编译基础设施的内部改进,使用新的 BTA 作为默认编译管道。对开发者来说最直接的影响是——未来 Kotlin 编译器的构建工具支持迭代会更快。
5. Maven 项目配置简化
Maven 用户收到了一个贴心更新。
在 pom.xml 的 Kotlin Maven 插件中加入 <extensions>true</extensions>,即可获得自动配置:
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>2.3.20-RC2</version>
<extensions>true</extensions>
</plugin>
开启后自动获得:
- 自动创建
src/main/kotlin和src/test/kotlin目录 - 自动添加
kotlin-stdlib依赖
如果你不想要这些默认行为,可以通过属性关闭:
<properties>
<kotlin.smart.defaults.enabled>false</kotlin.smart.defaults.enabled>
</properties>
6. 标准库新增 Map.Entry.copy()
标准库新增了 Map.Entry.copy() 扩展函数,用于创建 Map.Entry 的不可变副本。
这个 API 解决了一个经典问题:当你从 MutableMap 中获取 entry 并存储引用后,原 map 的修改可能导致 entry 失效。现在可以这样安全操作:
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val map = mutableMapOf(1 to 1, 2 to 2, 3 to 3, 4 to 4)
val toRemove = map.entries
.filter { it.key % 2 == 0 }
.map { it.copy() } // 创建不可变副本
map.entries.removeAll(toRemove)
println("map = $map") // map = {1=1, 3=3}
}
目前需要 @OptIn(ExperimentalStdlibApi::class) 才能使用。
升级建议
Kotlin 2.3.20-RC2 是一个面向稳定版的候选发布。如果你想提前体验:
- 在
build.gradle.kts中将 Kotlin 版本改为2.3.20-RC2 - 最新的 IntelliJ IDEA 和 Android Studio 已内置支持,无需额外更新 IDE 插件
建议先在非生产项目中测试,确认没有兼容性问题后再考虑在正式项目中采用。
写在最后
这次更新没有颠覆性的语言特性,但每一项改进都很务实:
- JPA 插件的 all-open 整合,直接消除了 Kotlin + Spring 的一个经典痛点
- Lombok Alpha 升级,给 Java 迁移 Kotlin 的团队吃了颗定心丸
- Kotlin/Native 新互操作模式,持续补齐 KMP 的短板
- 构建工具链的持续打磨,不管你用 Gradle 还是 Maven
Kotlin 团队一直在"做正确但不炫酷的事",而这恰恰是一个成熟语言该有的节奏。