Kotlin 1.3.60正式版发布

来为Kotlin 1.3.60正式版的发布而欢呼!除了质量的改进,下面是该版本的关键更新:

  • 优化了内联类的比较行为
  • 改进了测试工具,J2K转换器,Kotlin Gradle脚本编辑工具
  • Kotlin/Native支持更多平台
  • 改善了IDE对Kotlin/MPP的体验
  • 对于Kotlin/JS,添加了源映射的,并改善平台测试执行器的集成
  • 提供Kotlin1.4中已有实现的预览

你可以在更新日志中查阅完整的更新列表。我们仍然非常感谢所有外部的贡献者.

更多细节请让我娓娓道来。

语言的变化

小版本迭代不会带来语言的变更,除了小规模的改进(如改进令人迷惑的错误信息)或实验特性的更新(像内联类)。如想提前尝鲜Kotlin1.4,请阅读相应的文档

内联类的改进

对于内联类的比较,其类以内的数据类型会有一次不必要的装箱行为。但自1.3.60版本开始,里面数据类型的比较得以优化:

每个内联类的字节码都会生成一个特殊的静态方法equals-impl0,用于比对类中的数据类型。当你在非装箱实例上进行比对时,其隐式调用会避免额外的装箱行为。

请注意,暂时无法为内联类复写equals/hashCode方法。生成的equals-impl0 方法只是简单比较数据。在未来的版本,当允许内联类自定义equals方法时,内部仍然会调用相同的equals-imp0方法。

由于兼容性的原因,该优化只适用于Kotlin1.4版本的kotlin.Result类。

错误信息的改进

在小部分的情况下,编译错误信息并不能明确地告知你错误发生的原因。我们尝试改善并减少会带来疑惑的错误信息。

Kotlin支持trailing lambda convention:lambda允许在括号之外。同样允许lambda另起一行。但当编译器认为新一行的大括号是函数的参数时,可能会产生歧义:

对于这种情况的错误信息现在得以改进了。你可以执行简单的自动修复方案:在上一行的末尾插入一个分号。(没错,Kotlin有些时候也是需要分号的!)

另一个值得强调的情况是针对可变惰性常量。惰性变量设计上是只读的,但这设计可能会引起疑惑。现在其错误信息得以改进并提供了自动的修复捷径:

如果你遇到其他容易疑惑的用例,或你缺少部分非常有用的修复捷径,请在问题跟踪器提交这些请求。

IntelliJ IDEA支持

Scratches和Worksheets

我们重新设计并改良了Scratch文件,其目的是允许你以最小的代码库进行试验。现在可以在不同的窗口更方便地查看结果。涉及多行输出的结果会被包裹起来,同时高亮特定行。

有些时候Scratch文件并不能很好地执行。在如创建demo项目,展示特性等出于教学目的的场景下,你会更倾向于在项目内部而非外部去创建这些用例。对于这些需求,请使用Kotlin的Worksheets:

Kotlin Worksheets从概念上和技术上来说,与Scratch非常相似:你可以使用代码库并立即查看结果。两者之间的主要区别在于Worksheets是项目的一部分,这意味着可以通过VCS管理,而Scratches设计初衷是项目外的一部分。

build.gradle.kts

我们仍致力于提高你在编写Kotlin Gradle构建脚本的体验。着重强调的性能改善已经完成。我们会继续与Gradle紧密合作以不断改进。

Debugging改善

现在你可以在Kotlin函数中设置断点了。调试器会在进入或退出对应函数时暂停。你同样可以根据需求设置条件:

自动补全和导入的改善

几个已知的错误已经被修复了,如自动补全在包名和本地变量名重叠时的情况:

现在当你为枚举重新定义名称时,它的成员能在自动补全候选框中正常显示了:

如果你用到invoke这样的可省略语法操作符,IntelliJ IDEA建议你使用自动导入:

新的Java-to-Kotlin转换器

我们为新的Java-to-Kotlin加入了很多优秀的设计。解决了很多特殊情况,例如,现在能正确分析并转换静态导入和各种用法的集合,集合将能正确转换成可变或只读,无论该集合是否为通用参数。

现在,当你一次转换多个文件时,它们将会被共同分析,每个文件的内容都会影响最后输出的结果。 例如,你将null作为String参数传递给Java中的foo函数,则转换后的Kotlin函数参数是String?

新的转换器现在将被默认启用。

Eclipse IDE插件的更新

我们非常高兴地宣布kotlin-eclipse插件现已支持单个模块的实验性增量编译。在eclipse设置的Kotlin | Building部分勾”incremental compilation”以尝试该功能。由于这是一个实验性特性,我们非常欢迎你的任何反馈!

EclipseScreenshot

Kotlin/Multiplatform

我们将重心放在MPP工具上了,若有和你的此前预期不一致的地方,请尝试新的改进!

尽管未来的正式版会在Kotlin的多平台方面带来更强大的功能,但当前版本着重改进/修复IDE的许多可用性问题。 尤其我们极大增强了一些“create expect”快速修复的功能。

Kotlin/Native

Kotlin/Native编译器获得了很多新功能:

  • 和最新工具的兼容性:XCodeLLVM 8.0
  • 更多的新平台
    • watchOS
      • watchos_x86
      • watchos_arm64
      • watchos_arm32
    • tvOS
      • tvos_x64
      • tvos_arm64
    • Android (native)
      • android_x86
      • android_x64
  • 针对正式版二进制文件的iOS崩溃报告的实验性symbolication(包括LLVM内联代码,比XCode可解码的代码更为先进)。
  • 对Kotlin对象的Objective-C弱引用/共享引用的线程安全追踪。
  • 支持对suspend callable的引用.
  • “无限”可变参数函数 (受限于JVM限制)
  • work queue将能和任何上下文/线程关联,而不仅仅是通过Worker.start临时创建的上下文/线程。

通用Kotlin/Multiplatform命令行解析器

你们可能有人已经注意到kotlinx.cli 项目已经停更了几个月。 我们很高兴分享该项目,其中大部分的代码已被重写,并且它也包含在此版本的Kotlin/Native编译器中。

我们感谢早期新技术开荒用户的反馈! 你可以查看某些示例(俄罗斯方块, CSV解析器, ‍视频播放器)的用法,和内部的用法。

性能

尽管Kotlin/Native编译器还未对性能进行深度优化。但该正式版所带来的一些速度提升已足以让人惊讶。

对于大型项目,通过直接从klib(而不是源代码)生成本机库来提高了编译速度。

运行时性能也得到了改善:接口调用现在快了5倍,类型检查快了50倍

修复

  • 对于内联代码缺少debug所需要信息:部分内联优化会遗漏更新对于源码行号和实际字节码位置间的映射,这会导致设置断点的行为产生异常,导致超出目标位置的情况。我们已经提高了它们的记性,现在断点能正常执行了。
  • 向可变参数传递null当向具有可变参数的函数传递null时,例如:platform.posix.printf(“%p”, null)编译器会因为无法判断实际的类型而崩溃。请注意,现在我们会将该值视为COpaquePointer:无类型/ void指针,等效于C中的void *。
  • 为iOS/macOS的负值拆箱有些时候,处理负数字节会导致严重的崩溃;这是LLVM上的一个BUG,我们建议通过手动的方案去解决。从当前正式版开始,这个解决方案由编译器自动执行。

Kotlin/JS

在Kotlin/JS领域,org.jetbrains.kotlin.js新插件所带来的改进将能提升你的生活品质和简化你的工作。尤其是对源映射的支持和测试运行器的改进。

源映射

在Kotlin 1.3.60,可以通过org.jetbrains.kotlin.jsGradle插件自动为以JavaScript为目标的代码生成源映射。当你遇到错误时它可以提供可供阅读的堆栈跟踪信息,这使你可以更轻松地调试自己的代码,断点,代码注释,局部变量等的支持,将是浏览器开发工具的黑科技。下一段落将介绍如何简化JS平台的测试工作。

source-maps

测试运行器的改进

当你在JS平台上运行测试,生成的Gradle报告将包含常规通道的标准输出(即log,warn,error)。该功能允许在Node.js或浏览器平台上启用。这与源映射的集成使测试的堆栈跟踪更易于阅读,并方便与代码结合分析——文件名和行号直接指向你的Kotlin源代码:

test-runner

JS平台已支持测试过滤器,意味着可以有选择性地运行测试,而无需每次都得完整执行所有测试任务。你可以通过在Gradle命令行中指定--tests标记使用该功能:

你也可以使用IntelliJ IDEA中的 gutter图标来运行单个测试或指定组合的测试:

gutter-icons

Kotlin1.4即将到来的变化

Kotlin 1.4将计划在2020年发布。但你可以通过指定相应的语言版本来尝试一些已实现的特性:

请注意当前Kotlin1.4还在试验性状态

NPE断言

通过设置apiVersion1.4,你可以看到此前介绍过的空检查优化。下面的代码将会抛出一个NullPointerException,而非IllegalStateException以及旧的错误信息"JavaCode.getNull() must not be null"

when里的break和continue

Kotlin1.4其中一个语言层面上的变化是允许在when里面使用breakcontinue了。当前禁止使用不带标签的breakcontinue,是因为这些关键字作为when的fall-through的可能候选。 但是使用标签非常麻烦,因此breakcontinue能在外部存在循环下正确执行 :

when的fall-through行为有待设计。

尾递归函数的变化

我们准备修复尾递归函数在”特殊情况”下的一些特定行为。

默认函数的初始化顺序

当你的尾递归函数定义了具有副作用的默认值时,这个更改才有意义。 在Kotlin 1.3中,tailrec函数内的默认值的初始化顺序是错误的:默认值初始化顺序是从尾向头,即使反之亦然,从头向尾,这个规则同样适用于普通函数。

通过下面的例子可以明显看到区别:

在Kotlin1.3,输出是:

在Kotlin1.4,输出是:

我们希望实际情况中尽量不要采取这种写法。 (但如果由于某种原因你使用了这种复杂组合的语言特性,请注意这一即将到来的变化。)

在Kotlin 1.3中,结合使用open和tailrec修饰符是一个警告,在Kotlin 1.4中,它将成为错误。 请注意,这是一个“重大变化”:过去可以正常工作的代码不再起作用,但是我们不希望这种情况在实践中使用。

禁止同时使用open tailrec修饰函数

在Kotlin 1.3中,同时使用opentailrec修饰符只是一个warning,但在Kotlin 1.4中,它将是一个error。 请注意,这是一个“有破坏性的变化”:过去可以正常工作的代码将报错,但是我们不建议在实际环境中采取如此写法。

目前尚无法明确open尾递归函数的行为该以尾递归为主还是oepn函数为主。 在Kotlin 1.3中,open修饰符会被“忽略”,但这容易让人产生疑惑:

这段代码的输出是:

foo的函数行为更倾向于尾递归函数的预期:它调用了自身并在底层执行了优化

当我们从Afoo函数中去除tailrec修饰符,它的输出会变成:

现在foo函数的行为更符合open函数的预期:首先,super.foo(count)显式调用父类A的函数。然后foo(count-1)是一个虚函数调用,实际调用的是子类B中的函数。

由于类似的行为存在歧义,因此Kotlin1.4中禁止同时使用opentailrec进行修饰。

如何更新

照旧,你可以在play.kotl.in在线试用Kotlin

  • Maven, Gradle, 和npm:编译器和标准库版本指定为1.3.60这里查看文档。
  • IntelliJ IDEAAndroid Studio:打开Tools | Kotlin | Configure Kotlin Plugin Updates然后点击“Check for updates now”按钮,更新Kotlin插件到1.3.60版本。
  • Eclipse:在Marketplace安装插件。
  • 命令行编译器:在Github release page下载最新版本。

若你在新版本中发现任何问题,欢迎在论坛或 Slack (点击获取邀请)里寻求帮助,或者在问题跟踪器提交问题。

Let’s Kotlin!

其他贡献者

我们特别感谢Steven Schäfer,他优化了内联类中的比较.

我们同样感谢PR被合并到该版本的其他贡献者:

  • Toshiaki Kameyama
  • Ivan Gavrilovic
  • Mads Ager
  • Mark Punzalan
  • pyos
  • Jake Wharton
  • Yanis Batura
  • ilgonmic
  • Kristoffer Andersen
  • Sebastian Schuberth
  • Kevin Bierhoff
  • scache
  • keijumt
  • Louis CAD
  • Matthew Gharrity
  • Jim Sproch
  • Jim S
  • Dereck Bridie
  • Sascha Peilicke
  • SatoShun
  • Sergey Bogolepov
  • Dat Trieu
  • Burak Eregar
  • Ty Smith
  • Vladimir Krivosheev
  • Alex Chmyr
此条目发表在官方博客分类目录。将固定链接加入收藏夹。

发表评论

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