Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.6.20 现已发布
Kotlin 1.6.20 已经正式发布。 本次更新提供了未来语言功能的预览,将分层结构设为多平台项目的默认结构,并为 JVM、JS 和 Native 平台带来性能改进。
在这篇博文中,您将看到以下改进的概览和其他进化变更的完整列表。
- 基于上下文接收器的原型,添加了对在 Kotlin/JVM 中定义依赖上下文的声明的支持。
- 得益于绝对不可空类型,提升了与泛型 Java 类和接口的互操作性。
- 通过 JVM IR 后端单模块并行编译加快了构建速度。
- 通过 Kotlin/JS IR 中的增量编译简化了开发体验。
- Kotlin/Native 性能改进。
- 借助多平台项目的分层结构简化了代码共享。
如何升级
如果您使用的是 IntelliJ IDEA 或 Android Studio,您可以通过提供的选项在第一时间内自动更新至最新版本。
主要更新
Kotlin/JVM 上下文接收器的原型
在 Kotlin 1.6.20 中,您将不再局限于一个接收器。 您可以通过在声明中添加上下文接收器来使函数、属性和类与上下文相关。 上下文声明的作用如下:
- 所有声明的上下文接收器都必须以隐式接收器的形式出现在调用者的作用域中。
- 它将声明的上下文接收器作为隐式接收器带入其正文作用域。
要在您的项目中启用上下文接收器,请使用 -Xcontext-receivers
编译器选项。 您可以在 KEEP 中找到关于该功能及其语法的详细介绍。请注意,该实现是一个原型。
- 在启用
-Xcontext-receivers
的情况下,编译器将生成不能用于生产代码的预发布二进制文件。 - 目前,IDE 对上下文接收器的支持并不完善。
绝对不可空类型
为了在扩展泛型 Java 类和接口时提升互操作性,在 Kotlin 1.6.20 中,您可以使用新语法 T & Any
将泛型类型形参在使用地点标记为绝对不可空。 该语法形式来自相交类型表示法,现在被限制为一个类型形参,&
左侧为可空上限,右侧为不可空 Any
:
将语言版本设置为 1.7 以启用该功能:
在 KEEP 中详细了解绝对不可空类型。
请注意,绝对不可空类型目前为测试版。 它们几乎已达到稳定状态,但未来可能需要迁移。 我们会尽最大努力减少您需要进行的变更。
支持在 JVM 后端中对单个模块进行并行编译
在 Kotlin 1.6.20 中,我们增加了实验性的 JVM IR 后端模式,希望可以并行编译一个模块中的所有文件。 并行编译最多可以将总编译时间缩短 15%。
使用编译器选项-Xbackend-threads
启用实验性并行后端模式。 为此选项使用以下参数:
N
等于要使用的线程数。 它不应大于 CPU 核心数,否则,由于线程间的上下文切换,并行化将不再有效0
表示为每个 CPU 核心使用一个线程
Gradle 可以并行运行任务,但是当项目(或项目的主要部分)从 Gradle 的角度来看是一项大任务时,这种类型的并行化并不会起到太大帮助。 如果您有一个非常大的单体模块,使用并行编译可以加快编译速度。 如果项目包含许多小模块并且有一个由 Gradle 并行化的构建,那么添加另一层并行化可能会因为上下文切换而损害性能。
并行编译有一些限制:
- 它不适用于 kapt,因为 kapt 会禁用 IR 后端。
- 它在设计上需要更多的 JVM 堆。 堆的数量与线程的数量成正比。
采用 Kotlin/JS IR 编译器的开发二进制文件的增量编译
为了让采用 IR 编译器的 Kotlin/JS 开发更加高效,我们引入了一种新的增量编译模式。
在此模式下使用 compileDevelopmentExecutableKotlinJs
Gradle 任务构建开发二进制文件时,编译器会在模块级别缓存先前编译的结果。 它在后续编译过程中会为没有变化的源文件使用缓存的编译结果,使其能够更快完成,特别是变更较小的情况。 请注意,这项改进专门针对开发过程(缩短编辑-构建-调试周期),不影响生产工件的构建。
要为开发二进制文件启用增量编译,请将以下行添加到项目的 gradle.properties
中:
在我们的测试项目中,新模式最快将增量编译速度提高了 30%。但是,由于需要创建和填充缓存,干净构建在这种模式下变慢了。
Kotlin/Native 性能改进
Kotlin 1.6.20 带来了一些影响 Kotlin 生成的 LLVM IR 的性能更新和错误修正。 根据我们内部项目的基准,我们平均实现了以下性能提升:
- 执行时间缩短 15%
- 发布和调试二进制文件的代码大小缩减 20%
- 发布二进制文件的编译时间缩短 26%
这些变更还使大型内部项目的调试二进制文件的编译时间缩短了 10%。
为了实现这一点,我们为一些编译器生成的合成对象实现了静态初始化,改进了我们为每个函数构建 LLVM IR 的方式,并优化了编译器缓存。
多平台项目的分层结构支持
Kotlin 1.6.20 默认启用分层结构支持。 在 Kotlin 1.4.0 中引入后,我们显著改进了前端并稳定了 IDE 导入。
此前,您可以通过两种方式在多平台项目中添加代码。 第一种是将其插入针对特定平台的源集中,该源集仅限于一个目标,不能被其他平台重用。 第二种是使用在 Kotlin 当前支持的所有平台上共享的通用源集。
现在,对于重用许多通用逻辑和第三方 API 的原生目标,您可以在多个相似的原生目标之间共享源代码。 该技术将提供正确的默认依赖项,并在共享代码中找到可用的确切 API。 这消除了复杂的构建设置,并且不需要为了在原生目标之间共享源集而使用变通方法来获得 IDE 支持。 它还有助于防止针对不同目标的不安全 API 用法。
该技术也将对库作者派上用场,因为分层项目结构允许他们为目标子集发布和使用具有通用 API 的库。
默认情况下,使用分层项目结构发布的库仅与分层结构项目兼容。 详细了解项目-库兼容性。
更出色的项目代码共享
如果没有分层结构支持,就没有直接的方式可以在部分而非所有Kotlin 目标之间共享代码。 一个流行的示例是在所有 iOS 目标之间共享代码并访问针对 iOS 的依赖项,例如 Foundation
。
得益于分层项目结构支持,您现在开箱即可实现这一目标。 在新结构中,源集形成分层结构。 您可以使用给定源集编译成的每个目标可用的针对特定平台的语言功能和依赖项。
例如,一个具有两个目标的典型多平台项目 – 用于 iOS 设备和模拟器的 iosArm64
和 iosX64
。 Kotlin 工具了解两个目标具有相同的函数,并允许您从中间源集 iosMain
访问该函数。
Kotlin 工具链提供正确的默认依赖项,如 Kotlin/Native stdlib 或原生库。 此外,Kotlin 工具将尽最大努力找到共享代码中可用的确切 API 表面积。 这可以防止在为 Windows 共享的代码中使用针对 macOS 的函数等情况。
为库开发者提供更多机会
当一个多平台库发布时,其中间源集的 API 现在会一并正确发布,可供消费者使用。 同样,Kotlin 工具链将自动找出消费者源集中可用的 API,同时注意不安全的用法,例如在 JS 代码中使用用于 JVM 的 API。 详细了解在库中共享代码。
配置和设置
从Kotlin 1.6.20开始,所有新的多平台项目都将有一个分层项目结构。 无需其他设置。
- 如果您已经将其手动打开,您可以从
gradle.properties
中移除已弃用的选项:
- 对于 Kotlin 1.6.20,我们建议使用 Android Studio 2021.1.1 (Bumblebee) 或更高版本以获得最佳体验。
- 您也可以选择停用。 要禁用分层结构支持,请在
gradle.properties
中设置以下选项:
完整的改进列表
语言
Kotlin/JVM
Kotlin/Native
- 新内存管理器的更新
- 新内存管理器中扫描阶段的并发实现
- 注解类的实例化
- 与 Swift async/await 互操作:返回
Void
,而不是KotlinUnit
- 使用
libbacktrace
实现更好的堆栈跟踪。 - 支持独立 Android 可执行文件
- 性能改进
- 改进了 cinterop 模块导入期间的错误处理
- 支持 Xcode 13 库
Kotlin 跨平台
Kotlin/JS
- 采用 IR 编译器的开发二进制文件的增量编译
- 采用 IR 编译器时默认延迟顶层属性初始化
- 采用 IR 编译器时默认为项目模块生成单独的 JS 文件
Char
类优化- 导出和 TypeScript 声明生成改进
@AfterTest
保证异步测试
安全
Gradle
如何安装 Kotlin 1.6.20
如果您使用的是 IntelliJ IDEA 或 Android Studio,您的 IDE 会自动建议将 Kotlin 更新至 1.6.20。 您也可以按照这些说明手动更新。
您可以下载这些 IDE 的最新版本以获得对 Kotlin 的全面支持:
- IntelliJ IDEA – 用于为不同平台开发 Kotlin 应用程序。
- Android Studio – 用于开发 Android 和跨平台移动应用程序。
确保您同时已将 kotlinx 库更新到兼容版本,并在现有项目的构建脚本中指定 1.6.20 版本的 Kotlin。
如果需要命令行编译器,请从 GitHub 版本页面下载。
如果遇到任何问题
及时了解 Kotlin 最新功能! 填写本文右侧的表格以订阅接收 Kotlin 动态。
其他文章和视频
本博文英文原作者:
特别感谢由来自 Kotlin 社区的 xiaoshen (@smallshen) 参与贡献本文翻译。