kotlin
val (email, username) = user
你确定没写反?
如果 User 的属性顺序是 (username, email),恭喜你,这段代码已经悄悄埋了一个 bug。更可怕的是,两个属性都是 String 类型,编译器不会报任何错误。
Kotlin 2.3.20 刚刚发布,最大的亮点就是:解构声明终于支持按名称匹配了。
这个被社区呼吁了多年的特性,终于落地。

Position-Based:一个沉默的陷阱
Kotlin 的 data class 解构声明,一直以来都是按位置匹配的。编译器在背后生成 component1()、component2() 这样的函数,变量按顺序绑定。
kotlin
data class User(val username: String, val email: String)
val (first, second) = user
// first = username (component1)
// second = email (component2)
属性少的时候还好。但一旦属性多了,或者属性类型相同,就变成了定时炸弹。
想象一下:你的同事重构了 User,把 email 提到了第一个参数。你项目里所有的 val (username, email) = user 全部静悄悄地交换了值。
没有编译错误,没有运行时异常,只有一个"为什么用户收到的邮件称呼变成了邮箱地址"的线上 bug。

Name-Based Destructuring 来了
Kotlin 2.3.20 引入了基于名称的解构声明。变量不再按位置绑定,而是按名称匹配属性。
完整形式的语法长这样:
kotlin
val (name = username, mail = email) = user
// name 绑定到 username 属性
// mail 绑定到 email 属性
// 顺序无关!
等号左边是你定义的局部变量名,右边是要匹配的属性名。顺序不再重要。
如果你的局部变量名和属性名一致,还有更简洁的写法(需要开启 complete 模式):
kotlin
val (email, username) = user
// 自动按名称匹配,不再按位置
而如果你确实需要按位置匹配,改用方括号:
kotlin
val [first, second] = user
// 方括号 = 位置匹配(component1, component2)
圆括号按名称,方括号按位置。语义清晰,不再模糊。
怎么启用
目前提供了三种渐进模式,在 build.gradle.kts 中配置:
kotlin
kotlin {
compilerOptions {
freeCompilerArgs.add(
"-Xname-based-destructuring=name-mismatch"
)
}
}
三种模式的区别:
- only-syntax :仅启用显式的完整形式
val (a = propName) = obj - name-mismatch:变量名和属性名不匹配时发出警告(推荐先用这个)
- complete :完全启用,短形式
()按名称匹配,位置匹配改用[]
建议从 name-mismatch 开始。让编译器帮你排查现有代码中潜在的问题,再逐步迁移到 complete。

JPA 开发者的福音
用 Kotlin 写 JPA 实体类的同学,一定踩过这个坑:Kotlin 的 class 默认是 final 的,而 JPA 的懒加载需要生成代理类,代理类要求实体类必须是 open 的。
以前你得手动配置两个插件:
kotlin
// Before: 要写一堆配置
plugins {
kotlin("plugin.jpa")
kotlin("plugin.allopen") // 还得额外加这个
}
allOpen {
annotation("jakarta.persistence.Entity")
annotation("jakarta.persistence.Embeddable")
annotation("jakarta.persistence.MappedSuperclass")
}
Kotlin 2.3.20 之后,plugin.jpa 自动搞定一切:
kotlin
// After: 一行搞定
plugins {
kotlin("plugin.jpa")
}
// all-open 自动应用,JPA 注解预设内置
同时支持 javax.persistence 和 jakarta.persistence。Maven 用户同样受益------kotlin-maven-noarg 现在隐式包含了 kotlin-maven-allopen。
Kotlin/Wasm 性能起飞
如果你在关注 Kotlin Multiplatform 的 Web 端,这个版本的 Wasm 目标有了质的飞跃:
- 字符串插值性能提升最高 4.6 倍
- 产物体积减小约 5%
- 全量构建速度提升 65%
- 增量构建速度提升 21%
这些不是微优化。特别是构建速度------全量构建快了将近两倍,日常开发的体感会非常明显。
此外,新增了 @nativeInvoke 注解,允许 Kotlin 对象在 JavaScript 中直接作为函数调用。

TypeScript 可以实现 Kotlin 接口了
Kotlin/JS 终于支持从 TypeScript 直接实现 Kotlin 接口。这对 KMP 生态来说是一个重要的里程碑。
Kotlin 侧定义并导出接口:
kotlin
@JsExport
interface DataProcessor {
suspend fun process(): String
}
TypeScript 侧直接实现:
typescript
class JsonProcessor implements DataProcessor {
readonly [DataProcessor.Symbol] = true
async process(): Promise<string> {
return "processed JSON data"
}
}
Kotlin 定义契约,各平台用最自然的方式实现。"共享业务逻辑层"这个愿景又近了一步。
其他值得关注的变化
Maven 配置简化 :kotlin-maven-plugin 加一行 <extensions>true</extensions>,就能自动注册源码目录和 stdlib 依赖,不用再手写 <sourceDirectory> 了。
Vert.x 空安全 :编译器现在能识别 Vert.x 的 @Nullable 注解,自动推断为可空类型。
Java 只读集合 :@Unmodifiable 和 @UnmodifiableView 标记的集合,在 Kotlin 中会被视为只读类型。目前是警告,2.5.0 将升级为错误。
Map.Entry.copy() :新增实验性 API,可以创建 Map.Entry 的不可变副本。在遍历并修改 Map 时保留 entry 引用,非常实用。
Lombok 插件升级到 Alpha:从实验状态提升,JetBrains 计划做到生产可用。Kotlin/Java 混合项目的好消息。
Gradle 兼容范围:支持 Gradle 7.6.3 到 9.3.0,JVM 编译默认使用 Build Tools API。
如何升级
kotlin
plugins {
kotlin("jvm") version "2.3.20"
}
最新版 IntelliJ IDEA 和 Android Studio 已内置支持。命令行编译器可以从 GitHub Release 页面下载。
写在最后
Kotlin 2.3.20 是一个增量版本,但基于名称的解构声明是一个期待已久的语言级改进。它解决的不是什么"高级"问题,而是每个 Kotlin 开发者都可能踩到的坑。
JPA 插件的简化、Wasm 的性能飞跃、TypeScript 互操作的突破,也反映出 Kotlin 团队在多个方向上的持续发力。
你之前被解构声明的顺序坑过吗?欢迎评论区分享你的经历!