Kotlin 1.4.20发布!

Kotlin 1.4.20正带着新的实验特性向你走来。Kotlin团队始终如一地接纳社区的反馈,我们需要你对新特性原型的想法。尝试一下,并在Slack(点击获取邀请)或YouTrack进行反馈。

Kotlin 1.4.20

下面是部分关键点:

  • 支持新的JVM特性,例如通过invokedynamic实现字符串拼接。
  • 改善了KMM项目的性能和异常处理。
  • JDK Path类的扩展:Path("dir")/"file.txt"

我们还为现有功能(包括1.4.0中添加的特性)提供了许多修复和改进。因此,如果你在使用这些功能时遇到问题,现在是时候再次尝试了。

继续阅读以了解有关Kotlin 1.4.20特性的更多信息。还可以在Kotlin文档Kotlin 1.4.20的新特性页面上找到该发行版的简介。完整的变更列表可以在更新日志中查阅。

与往常一样,我们要感谢外部贡献者为该版本提供的帮助。

下面让我们尽情感受更新的细节吧!

Kotlin/JVM

在JVM上,我们添加了新的目标JVM 15,主要侧重于改进现有功能和性能,以及修复错误。

通过invokedynamic实现字符串拼接

从Java 9开始,JVM上的字符串拼接通过动态方法调用实现了(字节码中的invokedynamic指令)。和以前的实现相比,它的速度更快,内存消耗更少,并已为将来的优化留出了空间,而无需改动字节码。

为了更优异的性能,我们已经着手在Kotlin中实现这个机制,同时在目标JMV9+上,字符串的拼接会编译为动态调用。

当前这是个实验特性,涵盖以下情况:

  • 运算符(a + b),显式调用(a.plus(b))以及方法引用((a::plus)(b))上的String.plus
  • data class和内联的toString方法。
  • 字符串模板,只有一个非常量参数的除外(参考KT-42457)。

要开启invokedynamic字符串拼接,请将-Xstring-concat配置及以下值之一添加到编译器选项中:

Kotlin/JS

Kotlin/JS继续快速发展,该版本带来了许多改进,包括其项目向导的新模板,更好控制项目配置的DSL等。新的IR编译器还采用了一种全新的方式来编译项目,这会忽略代码中的错误。

Gradle DSL的变动

Kotlin/JS Gradle DSL已经获得了许多更新,这些更新简化了项目的配置和自定义,包括对Webpack配置的调整,对自动生成的package.json文件的修改以及对transitive dependencies控制的改进。

单点配置webpack

Kotlin 1.4.20为browser目标引入了一个新的配置块,名为commonWebpackConfig。在其中,你可以从一个点调整通用设置,而无需复制webpackTaskrunTasktestTask的配置。

要默认启用所有三个任务的CSS支持,只需要在项目的build.gradle(.kts)中包含以下片段:

从Gradle自定义package.json

package.json文件通常定义了JavaScript项目的行为,识别可以执行的脚本,依赖配置等。它是Kotlin/JS项目在构建期间自动生成的。由于package.json的内容因项目而异,因此,我们收到了很多简化该文件的编辑的请求。

从Kotlin 1.4.20开始,你可以从Gradle构建脚本中将条目添加到package.json项目文件。要将自定义字段添加到package.json中,请使用compilations的packageJson块中的customField函数:

当构建项目时,下述块将被添加到配置文件中build/js/packages/projectName/package.json:

无论你是要向配置中添加scripts field,要从命令行简单地运行项目,还是要包含来自其他后处理工具的信息,我们都希望你能发现这种指定自定义字段的新方法很有用。

SYarn的选择性依赖项解析(实验)

当包含npm中的依赖项时,有时你希望能对依赖项(transitive dependencies)进行细粒度的控制。可能有许多原因。你要对正在使用的库其中之一的依赖项进行重要升级。或者,你可能想回滚对transitive dependency的更新,这个更新会中断应用程序的开发。Yarn的选择性依赖项解析让你可以覆盖原作者指定的依赖项,因此可以继续进行开发。

在Kotlin 1.4.20,我们提供了一种初步的(实验性)特性,可以从项目的Gradle构建脚本中配置这个特性。尽管我们仍在针对其余Kotlin/JS配置进行平滑的API集成,但是你已经可以通过YarnPlugin中的YarnRootExtension使用该特性了。要影响项目已发版的软件包,请使用resolution函数。在其参数中,指定包名称选择器(由Yarn指定)和所需的版本。

build.gradle.kts文件中选择性依赖项解析的示例配置如下所示:

在这个例子中,所有npm依赖项需要的react其版本都为16.0.0,而processor将收到其3.0.0版本的deamelize依赖项。此外,还可以将includeexclude调用传递给resolution块,这让你能够指定版本约束。

禁用精细工作区(实验)

为了加快构建时间,Kotlin/JS Gradle插件仅安装特定Gradle任务所需的依赖项。例如,仅当执行\*Run任务其一时才安装webpack-dev-server包,而不会在执行assemble任务时去安装。虽然这意味着避免了不必要的下载,但当并行运行多个Gradle进程时,仍然会有问题。当依赖发生冲突时,重复安装npm软件包可能会引发错误。

要解决这个问题,Kotlin 1.4.20包含一个新的(实验性)配置项来禁用这些所谓的精细工作区。像对选择性依赖项解析的实验性支持一样,该特性目前也可以通过YarnRootExtension访问,但可能会与Kotlin/JS Gradle DSL的其余部分集成更密切。请将以下片段添加到build.gradle.kts文件中来使用这个特性:

通过这个配置,Kotlin/JS Gradle插件将安装项目会用到的所有npm依赖项,包括当前未执行任务的依赖项。这意味着首次Gradle构建可能会花费一些时间,但是对于运行的所有任务,其下载的依赖项都是最新的。这样便能避免在并行运行多个Gradle进程时的冲突。

新的向导模板

为了能更简单地创建自定义项目,Kotlin的项目向导附带了针对Kotlin/JS应用程序的可调整新模板。同样浏览器和Node.js运行时环境都有模板。它们是你项目的最佳起点,并可以微调初始配置。包括启用新的IR编译器或配置其他支持库等等的设置。

在Kotlin 1.4.20,有三个可用的模板:

浏览器应用程序允许您设置在浏览器中运行的准系统Kotlin / JS Gradle项目。 React Application包含使用适当的kotlin包装器开始构建React应用所需的一切。它提供了用于启用样式表,导航组件和状态容器集成的选项。 Node.js应用程序会预先配置您的项目以在Node.js运行时中运行。它带有直接包含实验性kotlinx-nodejs软件包的选项,我们在上一篇文章中介绍了该软件包。

  • 浏览器应用 允许你创建在浏览器中运行的准系统Kotlin/JS Gradle项目。
  • React应用包含通过合适的kotlin包装器开始构建React App所需要的一切。它提供了用于启用样式表,导航组件和状态容器集成的配置项。
  • Node.js应用会预先配置你的项目以能在Node.js运行时中运行。提供了直接包含实验性kotlinx-nodejs包的配置项,我们在之前的文章中介绍了这个软件包。

忽略编译异常(实验)

在Kotlin 1.4.20中,我们也很高兴地展示Kotlin/JS IR编译器中可用的全新特性——忽略编译错误。这个特性能在一般情况无法通过编译的状态下也可以运行你的应用程序。例如,当你在进行复杂的重构或处理与编译异常完全无关的系统部分时。使用这种新的编译器模式,编译器将忽略任何错误代码,并用运行时异常对其进行替换,而不是停止编译。

Kotlin 1.4.20有两个忽略代码中编译异常的退让策略:

  • SEMANTIC模式下,编译器将接受语法上正确但在语义上没有意义的代码。例如,类型不匹配的语句(像是val x: String = 3)。
  • SYNTAX模式下,编译器接受任何代码,几遍它包含语法错误。无论你如何编码,编译器仍将尝试生成能运行的可执行文件。

作为实验性特性,忽略编译错误需要通过编译器配置项选择性加入。仅适用于Kotlin/JS IR编译器。请将以下片段添加到build.gradle.kts文件中以启用它:

我们希望在编写Kotlin/JS项目时,带错误的编译能让你重视反馈循环并提高迭代的速度。我们期待在YouTrack中收到你的反馈,以及尝试这个特性时发现的任何问题。

随着该特性实现的逐渐完善,我们还将在未来为Kotlin/JS Gradle DSL及其任务提供更深度的集成。

Kotlin/Native

在1.4.20,性能仍然是Kotlin/Native优先考虑的。这个领域的关键特性是逃逸分析机制的新原型,我们计划在未来的发行版中对其进行完善和改进。当然,还有一些较小的性能改进,例如更快的范围检查(in)。

另一方面,Kotlin/Native的开发在1.4.20中得到打磨,且修复了错误。我们已经解决了很多旧问题,以及1.4新特性所发现的问题,例如代码共享机制。一部分改进解决了在极端情况下Kotlin/Native与Kotlin/JVM之间的行为不一致问题,例如属性初始化或equalshashCode在函数引用上的工作方式。

最后,我们扩展了Objective-C的互操作能力,并提供了将Objective-C异常包装到Kotlin异常的选项,从而可以在Kotlin代码中处理它们。

逃逸分析

逃逸分析是编译器用于确定对象在栈上分配或”逃逸”到堆上的技术。在栈上进行分配更快,而且后续也不需要进行垃圾收集。

尽管Kotlin/Native已经存在局部逃逸分析,但我们现在介绍一种新的,更有效的全局逃逸分析的原型实现。在发行版本独立的编译阶段中执行这个操作(通过-opt编译器配置项)。

该原型已经产生了一些令人鼓舞的结果,例如基准测试的平均性能提高了10%。我们正在研究优化算法的方案,让更多对象能在栈上分配,进一步提升程序的性能。

在我们继续研究原型的同时,你可以通过尝试并分享实际项目中的结果为我们提供极大的帮助。

如果要禁用逃逸分析阶段,请使用-Xdisable-phases=EscapeAnalysis编译器配置项。

选择性Objective-C异常包装

Objective-C中异常的设计与Kotlin中的完全不同。它们初衷仅限于在发现开发中的错误。但从技术上来说,Objective-C库会在运行时抛出异常。此前在Kotlin/Native中没有处理这类异常的方式,因此遇到从库中抛出的NSException会导致整个Kotlin/Native程序终止运行。

在1.4.20,我们添加了一个配置项来处理运行时异常,避免程序崩溃。你可以选择通过Kotlin的ForeignException来封装NSException,以便在Kotlin代码中进行处理。这样的ForeignException包含对原始NSException的引用,该引用可获取根本原因的信息。

要启用对Objective-C异常的封装,请在cinterop调用中指定-Xforeign-exception-mode objc-wrap配置项,或将foreignExceptionMode=objc-wrap属性添加到.def文件。如果是通过CocoaPods进行集成,请在pod{}脚本构建块的依赖项中指定配置项,如下所示:

默认行为依旧如此:在Objective-C代码抛出异常时,程序终止运行。

CocoaPods插件改进

改进任务执行

在该正式版中,我们大大改善了任务的执行流程。例如,如果添加新的CocoaPods依赖,则不会重建现有的依赖关系。添加额外的目标也不会触发对现有目标依赖关系的重建。

DSL扩展

在1.4.20中,我们扩展了将CocoaPods以来添加到Kotlin项目中的DSL。

除了本地Pod和CocoaPods仓库中的Pod,你还可以添加对以下类型库的依赖:

  • 来自自定义仓库的第三方库。
  • 来自Git仓库的远程库。
  • 存档中的库(也可以通过任意HTTP地址获得)。
  • 静态库。
  • 具有自定义cinterop配置的库。

仍然支持之前的DSL语法。

在以下示例中,我们测试几个DSL的变化:

  • 来自Git仓库的第三方库的依赖。你可以通过相应的关键字来指定标签,提交或分支,例如:

还可以结合这些关键字来指定Pod的必要版本。

  • 来自自定义仓库的第三方库的依赖。 通过specRepos的参数来指定:

你可以在Kotlin with CocoaPods sample找到更多的Kotlin示例。

更新了Xcode的集成

为了更好地使用Xcode,Kotlin需要对Podfile进行一些更改:

  • 如果你的Kotlin Pod有任何Git,HTTP或specRepo pod的依赖关系,也需要在Podfile中指定它们。例如,如果你在CocoaPods仓库中添加了对AFNetworking的依赖,请也在Podfile中声明:
  • 当在自定义仓库添加库时,你也需要将其地址添加到Podfile的开始处

现在集成的错误在IntelliJ IDEA中有更详细的描述了,因此当Podfile有任何问题,你将了解到有关如何修复的信息。

看看CocoaPods的Kotlin示例withXcproject分支。它包含一个现有Xcode项目kotlin-cocoapods-xcproj集成的示例。

支持Xcode 12的库

我们增加了对Xcode 12附带的新库的支持。请尽情在你的Kotlin代码中使用它们!

多平台库的发布结构更新

在Kotlin 1.4.20之前,多平台库的发布会包含指定平台和元数据。但是,没有必要完全依赖元数据进行发布,因此从未明确使用这个工件。

从Kotlin 1.4.20开始,不再有单独的元数据发布。元数据工件已被包含在整个库的发布中,当被作为公共源集的依赖添加时,元数据工件将自动解析为合适平台特定的工件。

请注意,你不能将没有分类器的空工件添加到库的根模块下,以满足诸如Maven Central之类的仓库的要求,因为这会与模块中已包含的元数据工件发生冲突。

1.4.20所发布库的兼容性

如果你启用了分层项目架构的支持,并且想使用在Kotlin 1.4.20或更高版本中基于该支持发布的多平台库,则还需要将项目中的Kotlin升级到1.4.20或更高版本。

如果你是库的作者,并且在Kotlin 1.4.20+中发布了支持分层项目架构的多平台库,请记住,还处于旧版本Kotlin且启用了分层项目架构支持的用户将无法使用你的库。他们需要将Kotlin升级到1.4.20或更高版本。

但是,如果你和你的库的用户未启用分层项目架构的支持,则处于早期版本Kotlin用户仍然可以使用你的库。

了解有关发布多平台库的更多信息。

标准库的变动

java.nio.file.Path的扩展

从1.4.20开始,标准库提供了java.nio.file.Path的实验扩展。

像使用kotlin.io包中的java.io.File扩展一样,现在能以符合Kotlin的语言习惯去使用现代JVM的文件API了。不再需要调用Files的静态方法,因为它们中的大部分现在都已成为Path类型的扩展了。

这些扩展位于kotlin.io.path包中。由于Path本身可在JDK 7和更高版本中使用,因此该扩展放在kotlin-stdlib-jdk7模块中。为了使用它们,你需要选择加入实验注解ExperimentPathApi

我们要特别感谢贡献者AJ Alt对这些扩展所提交的初始PR。

String.replace函数的性能改进

我们一直乐于见到Kotlin社区所提出的改进建议,下面是其中一种情况。在这个发行版中,我们更改了String.replace()的函数实现。

区分大小写的版本基于indexOf来循环替换,而不区分大小写的版本通过正则表达式进行匹配。

在某些情况下,这项改进可加快函数的执行速度。

弃用Kotlin Android Extensions

自从我们创建Kotlin Android Extensions,它们为Kotlin在Android生态中的迅速普及中发挥了巨大作用。通过这些扩展,我们为开发人员提供了方便有效的工具,以减少样板代码:

  • 用于UI交互的Synthetic views(kotlinx.android.synthetics)。
  • Parcelable实现生成器(@Parcelize),用于以Parcel的形式传递对象。

起初,我们考虑过向kotlin-android-extensions添加更多组件。但最终没有实现,我们甚至收到了用户的请求,希望能插件独立出来。

另一方面,Android生态一直在发展,开发者不断发现能让工作更轻松的新工具。Google提供的原生方案现已弥补了Kotlin Android Extensions填补的部分空白。例如,对于UI交互的简洁语法,现在有Android Jetpack,它提供了取代findViewById视图绑定,就像Kotlin synthetics一样。

考虑到这两个因素,我们决定淘汰synthetics,以支持视图绑定,并为Parcelable实现生成器迁移到独立的插件。

在1.4.20,我们从kotlin-android-extensions中提取了Parcelable实现生成器,并为其余部分启动了弃用周期,该周期目前仅针对synthetics。现在可在警告状态下继续使用。但在未来你需要将项目切换到其他解决方案。这是将Android项目从synthetics迁移到视图绑定的指南

现在,可通过新的kotlin-parcelize plugin插件来使用Parcelable实现生成器。应用此插件以代替kotlin-android-extensions@Parcelize注解已移到kotlinx.parcelize包。请注意,不能同时应用kotlin-parcelizekotlin-android-extensions到相同模块中。

如何更新

在将项目更新到最新版本的Kotlin之前,可以在play.kotl.in在线尝试新的语言和标准库特性。它将很快更新到1.4.20。

在IntelliJ IDEA和Android Studio,你可以更新Kotlin插件到1.4.20版本。操作指南

如果要在通过早期Kotlin版本创建的项目上使用,请在项目配置中使用1.4.20 Kotlin版本。 有关更多信息,请参阅GradleMaven的文档。

你可以在-Github发行页](https://github.com/JetBrains/kotlin/releases/tag/v1.4.20)下载命令行编译器。

你可以使用随版本发行的库的以下版本:

可以在相应的仓库中找到kotlin-wrappers库的不同版本(kotlin-react等)。

这里查看有关发行版的更多细节和兼容库列表。

如果你在新版本中遇到任何问题,可以在Slack找到帮助(在这里获得邀请)并在我们的YouTrack中报告问题。

其他贡献者

同样感谢提交的PR合并到该版本中的所有其他贡献者:

Jinseong Jeon
Toshiaki Kameyama
Steven Schäfer
Mads Ager
Mark Punzalan
Ivan Gavrilovic
pyos
Jim Sproch
Kristoffer Andersen
Aleksandrina Streltsova
cketti
Konstantin Virolainen
AJ Alt
Henrik Tunedal
Juan Chen
KotlinIsland,
Valeriy Vyrva
Alex Chmyr
Alexey Kudravtsev
Andrey Matveev
Aurimas Liutikas
Dat Trieu
Dereck Bridie
Efeturi Money
Elijah Verdoorn
Enteerman
fee1-dead
Francesco Vasco
Gia Thuan Lam
Guillaume Darmont
Jake Wharton
Julian Kotrba
Kevin Bierhoff
Matthew Gharrity
Matts966
Raluca Sauciuc
Ryan Nett
Sebastian Kaspari
Vladimir Krivosheev
n-p-s
Pavlos-Petros Tournaris
Robert Bares
Yoshinori Isogai
Kris
Derek Bodin
Dominik Wuttke
Sam Wang
Uzi Landsmann
Yuya Urano
Norbert Nogacki
Alexandre Juca

此条目发表在官方分类目录。将固定链接加入收藏夹。

发表评论

邮箱地址不会被公开。 必填项已用*标注