炉 VI · 回火CH 23进度 23/26

巡礼 2.0 → 2.4:K2 之后发生的一切

如果你有一段时间没跟 Kotlin 了 —— 换了岗位、去读书、或者只是项目锁死在某个版本上没人敢动 —— 这一章是你的补课清单。好消息是:Kotlin 没有背叛你,你会的东西一样没作废(向后兼容是它从 1.0 起的承诺)。你错过的是一批让你少写代码的东西,和一个让你每天少等一半编译时间的编译器。每一条我都标了版本和稳定状态:转正 可以直接用,实验 需要开关且语法可能还会变。

K22.0 → 2.4升级指南实验开关

先说最重要的那一件: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 工程师来说,按投入产出比排

排名特性为什么排这么高
1K2 编译器 2.0每天都在受益,零改动成本
2显式后备字段 2.4每个 ViewModel 都能删掉一对 _state/state(第 8 章)
3guard conditions 2.1UI 状态分派天天写(第 7 章)
4context parameters 2.4消灭参数穿透;也是 Arrow Raise 的地基(第 12、21 章)
5kotlin.time.Clock 2.3时间可注入 = 时间相关的逻辑可单测(第 12 章)
6未用返回值检查器 2.3能抓住「以为改了其实没改」这类真实 bug
7Rich 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 上用。你的实验特性会变成使用者的强制依赖。

升级怎么做(务实版)

  1. 先升 Kotlin 到 2.x(K2),别改任何代码。K2 更严格,可能会报出一批以前被漏掉的警告/错误 —— 那些大多是真的问题(老编译器的漏网之鱼),逐个修。
  2. 同步升 AGP 和 Gradle。版本矩阵有硬性要求(2.4 要求 AGP ≥ 8.5.2)—— 这通常是升级里最麻烦的一步,因为 AGP 会连带要求新的 JDK 和新的 Gradle。
  3. 检查 kapt。如果项目里还有 kapt(Dagger/Hilt/Room 的老配置),它会拖慢 K2 的收益 —— 迁移到 KSP2(第 24 章)。
  4. 开 IDE 的 K2 模式,享受更快的代码分析。
  5. 然后才开始用新语法。从显式后备字段和 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 是继任者 —— 而编译器插件正在悄悄地把越来越多的能力塞进你的字节码里。