Kotlin 1.4.20 新特性
Kotlin 1.4.20 提供了多项新的实验性特性,并为现有特性(包括 1.4.0 中添加的特性)提供了修复和改进。
你还可以在这篇博客文章中了解更多包含示例的新特性。
Kotlin/JVM
Kotlin/JVM 的改进旨在使其与现代 Java 版本的特性保持同步:
Java 15 目标平台
现在 Java 15 可作为 Kotlin/JVM 的目标平台。
invokedynamic 字符串连接
invokedynamic
字符串连接是实验性的。它可能随时被删除或更改。需要显式启用(详见下文)。仅用于求值目的。我们非常感谢你通过 YouTrack 提供反馈。
Kotlin 1.4.20 可以在 JVM 9+ 目标平台下将字符串连接编译为 动态调用,从而提升性能。
目前,此特性是实验性的,涵盖以下情况:
String.plus
的操作符形式 (a + b
)、显式形式 (a.plus(b)
) 和引用形式 ((a::plus)(b)
)。- 内联类和数据类上的
toString
。 - 字符串模板,但只有一个非常量实参的除外(请参阅 KT-42457)。
要启用 invokedynamic
字符串连接,请添加 -Xstring-concat
编译器选项并选择以下值之一:
indy-with-constants
:使用 StringConcatFactory.makeConcatWithConstants() 对字符串执行invokedynamic
连接。indy
:使用 StringConcatFactory.makeConcat() 对字符串执行invokedynamic
连接。inline
:切换回通过StringBuilder.append()
进行的经典连接。
Kotlin/JS
Kotlin/JS 持续快速发展,在 1.4.20 中,你可以找到多项实验性特性和改进:
Gradle DSL 变更
Kotlin/JS 的 Gradle DSL 收到多项更新,简化了项目设置和自定义。这包括 webpack 配置调整、自动生成的 package.json
文件修改,以及对传递性依赖项的改进控制。
webpack 配置的单一入口点
browser
目标平台现在提供一个新的配置块 commonWebpackConfig
。在其中,你可以从单一入口点调整通用设置,而无需为 webpackTask
、runTask
和 testTask
重复配置。
要为所有三个任务默认启用 CSS 支持,请在你的项目的 build.gradle(.kts)
文件中添加以下代码片段:
browser {
commonWebpackConfig {
cssSupport.enabled = true
}
binaries.executable()
}
了解更多关于 配置 webpack 打包 的信息。
通过 Gradle 进行 package.json 自定义
为了更好地控制 Kotlin/JS 包管理和发布,你现在可以通过 Gradle DSL 将属性添加到项目文件 package.json
中。
要将自定义字段添加到 package.json
,请在编译的 packageJson
代码块中使用 customField
函数:
kotlin {
js(BOTH) {
compilations["main"].packageJson {
customField("hello", mapOf("one" to 1, "two" to 2))
}
}
}
了解更多关于 package.json
自定义 的信息。
Yarn 选择性依赖项解析
Yarn 选择性依赖项解析的支持是实验性的。它可能随时被删除或更改。仅用于求值目的。我们非常感谢你通过 YouTrack 提供反馈。
Kotlin 1.4.20 提供了一种配置 Yarn 选择性依赖项解析 的方式——这是用于覆盖你所依赖的包的依赖项的机制。
你可以在 Gradle 中通过 YarnPlugin
内部的 YarnRootExtension
来使用它。要影响项目解析的包版本,请使用 resolution
函数,并传入包名选择器(由 Yarn 指定)和应解析到的版本。
rootProject.plugins.withType<YarnPlugin> {
rootProject.the<YarnRootExtension>().apply {
resolution("react", "16.0.0")
resolution("processor/decamelize", "3.0.0")
}
}
这里,你所有需要 react
的 npm 依赖项都将收到版本 16.0.0
,而 processor
将收到其依赖项 decamelize
的版本 3.0.0
。
禁用细粒度工作空间
为了加快构建时间,Kotlin/JS Gradle 插件只安装特定 Gradle 任务所需的依赖项。例如,webpack-dev-server
包只在你执行 *Run
任务之一时安装,而不在执行 assemble 任务时安装。这种行为在你并行运行多个 Gradle 进程时可能会带来问题。当依赖项要求冲突时,两次 npm 包安装可能会导致错误。
为了解决这个问题,Kotlin 1.4.20 包含一个选项来禁用这些所谓的“细粒度工作空间”。此特性目前通过 Gradle 中 YarnPlugin
内部的 YarnRootExtension
提供。要使用它,请将以下代码片段添加到你的 build.gradle.kts
文件中:
rootProject.plugins.withType<YarnPlugin> {
rootProject.the<YarnRootExtension>().disableGranularWorkspaces()
}
新向导模板
为了在项目创建过程中为你提供更便捷的自定义方式,Kotlin 的项目向导提供了新的 Kotlin/JS 应用程序模板:
- 浏览器应用程序 – 一个在浏览器中运行的最小 Kotlin/JS Gradle 项目。
- React 应用程序 – 一个使用相应
kotlin-wrappers
的 React 应用。它提供了启用样式表、导航组件或状态容器集成的选项。 - Node.js 应用程序 – 一个用于在 Node.js 运行时中运行的最小项目。它附带了一个选项,可以直接包含实验性的
kotlinx-nodejs
包。
IR 编译器忽略编译错误
忽略编译错误 模式是实验性的。它可能随时被删除或更改。需要显式启用(详见下文)。仅用于求值目的。我们非常感谢你通过 YouTrack 提供反馈。
Kotlin/JS 的 IR 编译器 带有一个新的实验性模式——带错误编译。在此模式下,即使代码包含错误,你也可以运行代码,例如,当整个应用程序尚未准备好时,你希望尝试某些功能。
此模式有两种容错策略:
SEMANTIC
:编译器将接受语法正确但语义上不合理的代码,例如val x: String = 3
。SYNTAX
:编译器将接受任何代码,即使它包含语法错误。
要允许带错误编译,请添加 -Xerror-tolerance-policy=
编译器选项并选择上述值之一。
Kotlin/Native
Kotlin/Native 在 1.4.20 中的优先级是性能和完善现有特性。以下是显著改进:
逃逸分析
Kotlin/Native 接收了一个新 逃逸分析 机制的原型。它通过在栈而不是堆上分配特定对象来提高运行时性能。此机制在我们的基准测试中显示出平均 10% 的性能提升,我们将继续改进它,以使其进一步加速程序。
逃逸分析在发布构建(使用 -opt
编译器选项)的单独编译阶段运行。
如果你想禁用逃逸分析阶段,请使用 -Xdisable-phases=EscapeAnalysis
编译器选项。
性能改进和 Bug 修复
Kotlin/Native 在各个组件中都接收到性能改进和 Bug 修复,包括 1.4.0 中添加的组件,例如代码共享机制。
Objective-C 异常的显式包装
Objective-C 异常包装机制是实验性的。它可能随时被删除或更改。需要显式启用(详见下文)。仅用于求值目的。我们非常感谢你通过 YouTrack 提供反馈。
Kotlin/Native 现在可以在运行时处理从 Objective-C 代码抛出的异常,以避免程序崩溃。
你可以选择启用将 NSException
包装成 ForeignException
类型的 Kotlin 异常。它们持有原始 NSException
的引用。这使你能够获取根本原因的信息并妥善处理。
要启用 Objective-C 异常的包装,请在 cinterop
调用中指定 -Xforeign-exception-mode objc-wrap
选项,或将 foreignExceptionMode = objc-wrap
属性添加到 .def
文件中。如果你使用 CocoaPods 集成,请在依赖项的 pod {}
构建脚本块中指定该选项,如下所示:
pod("foo") {
extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
}
默认行为保持不变:当从 Objective-C 代码抛出异常时,程序会终止。
CocoaPods 插件改进
Kotlin 1.4.20 延续了 CocoaPods 集成的一系列改进。具体来说,你可以尝试以下新特性:
改进的任务执行
CocoaPods 插件获得了改进的任务执行流。例如,如果你添加一个新的 CocoaPods 依赖项,现有依赖项不会重新构建。添加额外目标平台也不会影响现有依赖项的重新构建。
扩展的 DSL
向 Kotlin 项目添加 CocoaPods 依赖项的 DSL 获得了新功能。
除了本地 Pods 和来自 CocoaPods 版本库的 Pods,你还可以添加对以下类型库的依赖项:
- 来自自定义 spec 版本库的库。
- 来自 Git 版本库的远程库。
- 来自归档(也可通过任意 HTTP 地址获取)的库。
- 静态库。
- 带有自定义 cinterop 选项的库。
了解更多关于在 Kotlin 项目中添加 CocoaPods 依赖项 的信息。在 Kotlin with CocoaPods 示例 中查找示例。
更新的 Xcode 集成
为了与 Xcode 正常工作,Kotlin 需要对 Podfile 进行一些更改:
- 如果你的 Kotlin Pod 具有任何 Git、HTTP 或 specRepo Pod 依赖项,你也应该在 Podfile 中指定它。
- 当你从自定义 spec 添加库时,你还应该在 Podfile 的开头指定 specs 的位置。
现在集成错误在 IDEA 中有详细的描述。因此,如果你的 Podfile 出现问题,你将立即知道如何修复它们。
了解更多关于创建 Kotlin Pods 的信息。
支持 Xcode 12 库
我们增加了对 Xcode 12 随附的新库的支持。现在你可以从 Kotlin 代码中使用它们。
Kotlin 多平台
更新的多平台库发布结构
从 Kotlin 1.4.20 开始,不再有单独的元数据发布。元数据 artifact 现在包含在_根_发布中,根发布代表整个库,当作为依赖项添加到公共源代码集时,会自动解析为相应的平台特有 artifact。
了解更多关于发布多平台库 的信息。
与早期版本的兼容性
这种结构变化破坏了具有分层项目结构 的项目之间的兼容性。如果一个多平台项目及其所依赖的库都具有分层项目结构,那么你需要将它们同时更新到 Kotlin 1.4.20 或更高版本。使用 Kotlin 1.4.20 发布的库无法用于更早版本发布的项目。
没有分层项目结构的项目和库保持兼容。
标准库
Kotlin 1.4.20 的标准库提供了用于处理文件的新扩展和更好的性能。
java.nio.file.Path
的扩展
java.nio.file.Path
的扩展是实验性的。它们可能随时被删除或更改。需要显式启用(详见下文)。仅用于求值目的。我们非常感谢你通过 YouTrack 提供反馈。
现在标准库为 java.nio.file.Path
提供了实验性扩展。以惯用的 Kotlin 方式使用现代 JVM 文件 API 现在类似于使用 kotlin.io
包中的 java.io.File
扩展。
// construct path with the div (/) operator
val baseDir = Path("/base")
val subDir = baseDir / "subdirectory"
// list files in a directory
val kotlinFiles: List<Path> = Path("/home/user").listDirectoryEntries("*.kt")
这些扩展在 kotlin-stdlib-jdk7
模块的 kotlin.io.path
包中提供。要使用这些扩展,请显式启用 实验性注解 @ExperimentalPathApi
。
String.replace
函数性能改进
String.replace()
的新实现加速了函数执行。区分大小写的变体使用基于 indexOf
的手动替换循环,而不区分大小写的变体则使用正则表达式匹配。
Kotlin Android Extensions
在 1.4.20 中,Kotlin Android Extensions 插件被废弃,Parcelable
实现生成器移至单独的插件。
废弃合成视图
合成视图 是 Kotlin Android Extensions 插件在一段时间前引入的,旨在简化与 UI 元素的交互并减少样板代码。现在 Google 提供了一种实现相同功能的原生机制——Android Jetpack 的视图绑定,我们正在废弃合成视图以支持后者。
我们将 Parcelable
实现生成器从 kotlin-android-extensions
中提取出来,并开始对其余部分(合成视图)的废弃周期。目前,它们仍会带着废弃警告继续工作。将来,你需要将项目切换到其他解决方案。以下是指南,它将帮助你将 Android 项目从合成视图迁移到视图绑定。
Parcelable
实现生成器的新插件
Parcelable
实现生成器现在在新的 kotlin-parcelize
插件中可用。请应用此插件而非 kotlin-android-extensions
。
kotlin-parcelize
和kotlin-android-extensions
不能在同一模块中同时应用。
@Parcelize
注解已移至 kotlinx.parcelize
包。
了解更多关于 Parcelable
实现生成器在 Android 文档 中的信息。