13.6.10.1 Kotlin 1.4.30 的新变化
8 分钟阅读
13.6.10.1 Kotlin 1.4.30 的新变化
阅读 Kotlin 1.4.30 的发行说明,涵盖新的语言特性、Kotlin Multiplatform、JVM、Native、JS 的更新,以及对 Gradle 和 Maven 构建工具的支持。
Kotlin 1.4.30 提供了新语言特性的预览版本,把 Kotlin/JVM 编译器的新 IR 后端提升为 Beta,并带来了各种性能和功能改进。
你也可以在这篇博客文章中了解新特性。
提示: 关于 Kotlin 发布周期的信息,请参阅 Kotlin 发布流程。
语言特性
Kotlin 1.5.0 将带来新的语言特性 —— 支持 JVM record、密封接口以及稳定的内联类。在 Kotlin 1.4.30 中,你可以以预览模式试用这些特性和改进。如果你能在相应的 YouTrack 议题中与我们分享反馈,我们将非常感激,因为这让我们有机会在 1.5.0 发布之前处理它们。
要以预览模式启用这些语言特性和改进,你需要通过添加特定的编译器选项来选择启用。详见下文各节。
在这篇博客文章中进一步了解新特性预览。
JVM record 支持
警告: JVM record 特性是实验性的。它可能随时被移除或更改。需要选择启用(详见下文),并且你应仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
JDK 16 版本计划稳定一种名为 record 的新 Java 类类型。为了提供 Kotlin 的所有优势并维持其与 Java 的互操作,Kotlin 正在引入对 record 类的实验性支持。
你可以像使用带属性的 Kotlin 类一样使用在 Java 中声明的 record 类,无需任何额外步骤。
从 1.4.30 开始,你可以使用 @JvmRecord 注解为 data 类在 Kotlin 中声明 record 类:
| |
要试用 JVM record 的预览版本,请添加编译器选项 -Xjvm-enable-preview 和 -language-version 1.5。
我们仍在继续开发 JVM record 支持,如果你能通过这个 YouTrack 议题与我们分享反馈,我们将非常感激。
在 KEEP 中进一步了解其实现、限制和语法。
密封接口
警告: 密封接口是实验性的。它们可能随时被移除或更改。需要选择启用(详见下文),并且你应仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
在 Kotlin 1.4.30 中,我们提供了_密封接口_的原型。它们与密封类互补,让构建更灵活的受限类层次结构成为可能。
它们可以作为“内部”接口使用,无法在同一模块之外实现。例如,你可以依赖这一事实来编写穷尽的 when 表达式。
| |
另一个用例:有了密封接口,你可以让一个类继承自两个或多个密封父类型。
| |
要试用密封接口的预览版本,请添加编译器选项 -language-version 1.5。切换到该版本后,你就可以在接口上使用 sealed 修饰符。如果你能通过这个 YouTrack 议题与我们分享反馈,我们将非常感激。
包级密封类层次结构
警告: 包级密封类层次结构是实验性的。它们可能随时被移除或更改。需要选择启用(详见下文),并且你应仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
密封类现在可以组成更灵活的层次结构。它们可以在同一编译单元、同一包的所有文件中拥有子类。此前,所有子类都必须出现在同一个文件中。
直接子类可以是顶层的,也可以嵌套在任意数量的其他具名类、具名接口或具名对象内部。密封类的子类必须具有正确限定的名称 —— 它们不能是局部对象或匿名对象。
要试用包级密封类层次结构,请添加编译器选项 -language-version 1.5。如果你能通过这个 YouTrack 议题与我们分享反馈,我们将非常感激。
改进的内联类
警告: 内联值类处于 Beta 阶段。它们几乎已经稳定,但将来可能仍需要迁移步骤。我们会尽力把你需要做的改动降到最少。我们非常欢迎你在 YouTrack 上提供关于内联类特性的反馈。
Kotlin 1.4.30 把内联类提升为 Beta,并为它们带来以下特性和改进:
- 由于内联类是基于值的,你可以使用
value修饰符定义它们。inline和value修饰符现在彼此等价。在未来的 Kotlin 版本中,我们计划弃用inline修饰符。
从现在开始,对于 JVM 后端,Kotlin 要求类声明之前带有 @JvmInline 注解:
| |
- 内联类可以有
init块。你可以添加在类实例化之后立即执行的代码:
| |
- 从 Java 代码调用带内联类的函数:在 Kotlin 1.4.30 之前,由于名称改写,你无法从 Java 调用接受内联类的函数。从现在开始,你可以手动禁用名称改写。要从 Java 代码调用这类函数,应在函数声明之前添加
@JvmName注解:
| |
- 在本次发布中,我们修改了函数的名称改写方案以修复不正确的行为。这些改动导致了 ABI 变化。
从 1.4.30 开始,Kotlin 编译器默认使用新的名称改写方案。使用 -Xuse-14-inline-classes-mangling-scheme 编译器标志可以强制编译器使用旧的 1.4.0 改写方案并保持二进制兼容性。
Kotlin 1.4.30 把内联类提升为 Beta,我们计划在未来的版本中把它们变为稳定。如果你能通过这个 YouTrack 议题与我们分享反馈,我们将非常感激。
要试用内联类的预览版本,请添加编译器选项 -Xinline-classes 或 -language-version 1.5。
在 KEEP 中进一步了解名称改写算法。
Kotlin/JVM
JVM IR 编译器后端达到 Beta
面向 Kotlin/JVM 的基于 IR 的编译器后端在 1.4.0 中以 Alpha 形式推出,现在已达到 Beta。这是 IR 后端成为 Kotlin/JVM 编译器默认后端之前的最后一个预稳定级别。
我们现在取消了对消费 IR 编译器生成产物的限制。此前,只有在你启用了新后端的情况下,才能使用由新的 JVM IR 后端编译的代码。从 1.4.30 开始,不再有这样的限制,因此你可以使用新后端为第三方构建组件,例如库。试用新后端的 Beta 版本,并在我们的问题跟踪器中分享反馈。
要启用新的 JVM IR 后端,请在项目的配置文件中添加以下几行:
- 在 Gradle 中:
Kotlin
| |
Groovy
| |
- 在 Maven 中:
| |
在这篇博客文章中进一步了解 JVM IR 后端带来的变化。
Kotlin/Native
性能改进
Kotlin/Native 在 1.4.30 中获得了各种性能改进,从而缩短了编译时间。例如,使用 Kotlin Multiplatform Mobile 进行网络与数据存储示例中重建 framework 所需的时间从 9.5 秒(1.4.10 中)降至 4.5 秒(1.4.30 中)。
Apple watchOS 64 位模拟器目标
自 7.0 版本起,watchOS 的 x86 模拟器目标已被弃用。为了跟上最新的 watchOS 版本,Kotlin/Native 提供了新目标 watchosX64,用于在 64 位架构上运行模拟器。
支持 Xcode 12.2 库
我们添加了对 Xcode 12.2 提供的新库的支持。现在你可以在 Kotlin 代码中使用它们。
Kotlin/JS
顶层属性的惰性初始化
警告: 顶层属性的惰性初始化是实验性的。它可能随时被移除或更改。需要选择启用(详见下文),并且你应仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
Kotlin/JS 的 IR 后端正在获得顶层属性惰性初始化的原型实现。这减少了应用启动时需要初始化所有顶层属性的必要,应该能显著改善应用启动时间。
我们会继续改进惰性初始化,也请你试用当前的原型,并在这个 YouTrack 议题或官方 Kotlin Slack 的 #javascript 频道中分享你的想法和结果(在这里获取邀请)。
要使用惰性初始化,请在使用 JS IR 编译器编译代码时添加 -Xir-property-lazy-initialization 编译器选项。
Gradle 项目改进
支持 Gradle 配置缓存
从 1.4.30 开始,Kotlin Gradle 插件支持配置缓存特性。它会加快构建过程:一旦你运行命令,Gradle 就会执行配置阶段并计算任务图。Gradle 会缓存结果并在后续构建中复用。
要开始使用该特性,你可以使用 Gradle 命令或配置基于 IntelliJ 的 IDE。
标准库
与区域设置无关的大小写转换 API
警告: 与区域设置无关的 API 特性是实验性的。它可能随时被移除或更改。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
本次发布引入了实验性的、与区域设置无关的 API,用于改变字符串和字符的大小写。当前的 toLowerCase()、toUpperCase()、capitalize()、decapitalize() API 函数是区分区域设置的。这意味着不同的平台区域设置可能影响代码行为。例如在土耳其语区域设置中,用 toUpperCase 转换字符串 “kotlin” 的结果是 “KOTLİN”,而不是 “KOTLIN”。
| |
Kotlin 1.4.30 提供了以下替代方案:
- 对于
String函数:
|早期版本|1.4.30 替代方案|
|String.toUpperCase()|String.uppercase()|
|String.toLowerCase()|String.lowercase()|
|String.capitalize()|String.replaceFirstChar { it.uppercase() }|
|String.decapitalize()|String.replaceFirstChar { it.lowercase() }|
- 对于
Char函数:
|早期版本|1.4.30 替代方案|
|Char.toUpperCase()|Char.uppercaseChar(): CharChar.uppercase(): String|
|Char.toLowerCase()|Char.lowercaseChar(): CharChar.lowercase(): String|
|Char.toTitleCase()|Char.titlecaseChar(): CharChar.titlecase(): String|
注意: 对于 Kotlin/JVM,还有带显式
Locale参数的重载uppercase()、lowercase()和titlecase()函数。
在 KEEP 中查看文本处理函数变更的完整列表。
更清晰的 Char 与编码、Char 与数字之间的转换
警告:
Char转换的无歧义 API 特性是实验性的。它可能随时被移除或更改。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
当前的 Char 到数字转换函数返回以不同数值类型表示的 UTF-16 编码值,它们经常与类似的字符串到 Int 转换(后者返回字符串的数值)混淆:
| |
为避免这种混淆,我们决定把 Char 转换分成以下两组名称清晰的函数:
- 用于获取
Char的整数编码以及从给定编码构造Char的函数:
| |
- 用于把
Char转换为其所表示数字的数值的函数:
| |
- 一个
Int的扩展函数,用于把它所表示的非负单个数字转换为对应的Char表示:
| |
更多细节请参阅 KEEP。
序列化更新
随着 Kotlin 1.4.30 一同发布的还有 kotlinx.serialization 1.1.0-RC,其中包含一些新特性:
- 内联类的序列化支持
- 无符号原始类型的序列化支持
内联类的序列化支持
从 Kotlin 1.4.30 开始,你可以让内联类可序列化:
| |
注意: 该特性需要新的 1.4.30 IR 编译器。
当可序列化的内联类在其他可序列化类中使用时,序列化框架不会对它们进行装箱。
在 kotlinx.serialization 文档中了解更多。
无符号原始类型的序列化支持
从 1.4.30 开始,你可以对无符号原始类型 UInt、ULong、UByte 和 UShort 使用 kotlinx.serialization 的标准 JSON 序列化器:
| |
在 kotlinx.serialization 文档中了解更多。