巡礼 2.0 → 2.4:K2 之后发生的一切
如果你有一段时间没跟 Kotlin 了 —— 换了岗位、去读书、或者只是项目锁死在某个版本上没人敢动 —— 这一章是你的补课清单。好消息是:Kotlin 没有背叛你,你会的东西一样没作废(向后兼容是它从 1.0 起的承诺)。你错过的是一批让你少写代码的东西,和一个让你每天少等一半编译时间的编译器。每一条我都标了版本和稳定状态:转正 可以直接用,实验 需要开关且语法可能还会变。
先说最重要的那一件:K2
Kotlin 2.0(2024 年 5 月)把编译器前端整个重写了,代号 K2。这是十年来最大的一次内部变更,而它对你的意义分三层:
- 编译更快。大项目上前端速度提升显著(官方数据是约两倍,实际取决于项目结构)。这是你每天都在付的税,升级就是退税。
- 编译器更聪明。类型推断、智能转换(第 4 章)、穷尽检查(第 7 章)全面变强 —— 一批以前需要你手动帮忙的地方,现在它自己能推出来了。
- 它是地基。2.1 之后的每一个语言新特性(守卫条件、context parameters、Rich Errors)都是 K2 的新架构才做得出来的。不升 K2,后面的一切都与你无关。
如果你的项目还在 1.9.x —— 停下手上的活,先做这件事。这不是「要不要用新特性」的问题,是「要不要每天多等一倍编译时间」的问题。
时间线:点开看前后对照
下面每一项都给了「以前你得这么写 / 现在」的对照。按你的痛点挑着看 —— 如果你是 Android 开发,重点看 2.4 显式后备字段(ViewModel 样板砍半)和 2.1 guard conditions(when 分派):
Android 开发者的优先级排序
上面十几条不是同等重要的。对一个 Android 工程师来说,按投入产出比排:
| 排名 | 特性 | 为什么排这么高 |
|---|---|---|
| 1 | K2 编译器 2.0 | 每天都在受益,零改动成本 |
| 2 | 显式后备字段 2.4 | 每个 ViewModel 都能删掉一对 _state/state(第 8 章) |
| 3 | guard conditions 2.1 | UI 状态分派天天写(第 7 章) |
| 4 | context parameters 2.4 | 消灭参数穿透;也是 Arrow Raise 的地基(第 12、21 章) |
| 5 | kotlin.time.Clock 2.3 | 时间可注入 = 时间相关的逻辑可单测(第 12 章) |
| 6 | 未用返回值检查器 2.3 | 能抓住「以为改了其实没改」这类真实 bug |
| 7 | Rich Errors 2.4 | 方向正确,但还会变 —— 先理解,别重构(第 20 章) |
| 8 | 名字解构 2.3.20 | 修一个静默 bug,但影响面小(第 11 章) |
| — | 集合字面量 2.4 | 纯语法糖。好用,但不改变什么 |
实验特性的开关(抄这张表)
// build.gradle.kts
kotlin {
compilerOptions {
freeCompilerArgs.addAll(
"-Xreturn-value-checker=check", // 2.3 未用返回值检查
"-Xname-based-destructuring=only-syntax", // 2.3.20 名字解构
"-Xcollection-literals", // 2.4 集合字面量
"-Xexplicit-context-arguments" // 2.4 显式上下文实参
)
}
}
「实验」不是「不稳定到不能碰」,但它有明确的含义:语法可能会变,而变了之后你要改代码。
三条自律:
- 可以在新代码、内部工具、玩具项目里用。踩坑的成本可控。
- 别拿它当架构地基。context receivers 的教训就在眼前 —— 那套语法整个作废了(第 12 章)。
- 别在库的公开 API 上用。你的实验特性会变成使用者的强制依赖。
升级怎么做(务实版)
- 先升 Kotlin 到 2.x(K2),别改任何代码。K2 更严格,可能会报出一批以前被漏掉的警告/错误 —— 那些大多是真的问题(老编译器的漏网之鱼),逐个修。
- 同步升 AGP 和 Gradle。版本矩阵有硬性要求(2.4 要求 AGP ≥ 8.5.2)—— 这通常是升级里最麻烦的一步,因为 AGP 会连带要求新的 JDK 和新的 Gradle。
- 检查 kapt。如果项目里还有 kapt(Dagger/Hilt/Room 的老配置),它会拖慢 K2 的收益 —— 迁移到 KSP2(第 24 章)。
- 开 IDE 的 K2 模式,享受更快的代码分析。
- 然后才开始用新语法。从显式后备字段和 guard conditions 开始,它们改动小、收益直接、不需要说服任何人。
Kotlin 的演进方向非常清楚,而且和这本书前面 22 章讲的东西高度一致:
- 把更多东西搬进类型系统(Rich Errors 把失败搬进签名,context parameters 把依赖搬进签名)。
- 把样板交给编译器(显式后备字段、data class、集合字面量)。
- 把静默的错误变成编译错误(未用返回值检查、名字解构、穷尽检查)。
这三条,正是本书从第 1 章开始讲的同一件事:让编译器替你干活。—— 所以你不用担心「学的东西过时」:Kotlin 未来五年的方向,还是这个方向。
1. 现在就去看项目的 Kotlin 版本号。如果 < 2.0,把升级排进下个 sprint,理由写「编译时间减半」—— 这个理由比任何新特性都好卖。
2. 如果已经在 2.4:打开 -Xreturn-value-checker=check,编译一次。看它报出多少处「返回值被丢掉」 —— 每一处都是一个潜在的 bug。
3. 挑一个 ViewModel,用显式后备字段重写它的 StateFlow 属性。全项目推广,数一数删了多少行。
4. 把这一章的时间线转发给团队里那个「我们为什么要升 Kotlin」的人。
下一章:工具链。kapt 已经退休了,KSP2 是继任者 —— 而编译器插件正在悄悄地把越来越多的能力塞进你的字节码里。