Kotlin 1.3.50正式版发布

今天我们很高兴地迎来Kotlin 1.3.50版本的正式发布。除了一如以往的质量和工具的优化,该新版重点如下:

  • 提供了新的持续时间和测量时间API(仅供预览)
  • 改进了Java-to-Kotlin转换器
  • 尝试在Gradle Kotlin/JS项目中(使用Dukat)生成npm依赖项的外部声明
  • 用于在IntelliJ IDEA Ultimate中调试Kotlin/Native代码的独立插件
  • 多平台项目中支持Java编译

你可以在更新日志中查阅完整的列表。如往常一样,我们非常感谢外部的贡献者。下面一起来领略详尽的更新内容吧。

Kotlin 1.4针对空检查的优化

如你所知,Kotlin通过可空类型来避免发生NullPointerException异常。 但是与Java代码的互操作性导致无法完全避免NPE。 为了在NPE崩溃发生时,让开发人员更容易地查找到问题的根源,Kotlin编译器不止抛出NPE,还会抛出带有清晰错误消息的各种类型的运行时异常。 事实证明,这种方法有其缺点:它减少了可能由Kotlin编译器或各种字节码处理工具(例如Android R8优化器)执行的空检查优化。

为了解决这个问题,从Kotlin 1.4开始,所有运行时null检查都会抛出java.lang.NullPointerException而不是KotlinNullPointerExceptionIllegalStateExceptionIllegalArgumentExceptionTypeCastException。 这适用于!!操作符,method preamble中的参数null检查,平台类型的表达式null检查以及具有非null类型的as运算符。 这不适用于lateinit空检查和诸如checkNotNullrequireNotNull之类的显式库函数调用。

但是这不会对开发者有太大改变:Kotlin代码抛出的异常,其所携带的异常信息仍和以前一样。 异常的类型发生了变化,但是传递的信息保持不变。 例如,以下代码现在会抛出一个IllegalStateException,其错误消息为”JavaCode.getNull()不得为空”:

在第1行中的duplicate函数调用之前,将生成一个特殊检查,如果表达式JavaCode.getNull()存储null,则会抛出此异常。从Kotlin 1.4开始,此代码将抛出NullPointerException代替异常信息”JavaCode.getNull()不得为null”。

在这个变动后,优化器通过删除冗余空检查来尽可能地减少字节码中空检查的总数:由于所有检查都抛出相同的NPE异常,因此可以只保留一个NPE异常。在此种优化过程中,NPE中的一些有用信息可能会丢失,这就是获得更好性能所要付出的代价。请注意,这些优化方案只会在对应的工具中实现,并且在实现时会有更多详细信息,但是异常类型的变动可能会在未来版本实装。

标准库的变化

请留意所有新功能都以“实验”状态添加到标准库中。

持续时间和测量时间API

新的持续时间和时间测量API已提供预览版本。可通过秒,毫秒,纳秒等等多种单位度量持续时间。已知不同单位之间混用会导致bug:如果要求API将持续时间存储为像“ Long”这样的原始类型,则可能会使用错误的单位传递值,不幸的是类型系统无法协助避免这种情况。尽管创建一个常规类来存储持续时间可以解决这个问题,但又带来了另一个问题:额外的消耗。

内联类提供了一个非常优雅的解决方案:它既保证了类型,也不会产生消耗。现在,API可以使用Duration类型,并且所有客户端都需要显式指定单位。由于Duration被声明为一个内联类,因此不需要额外的消耗:

这个版本支持单调时钟”MonoClock”。推荐使用单调时钟来从程序中给定点开始测量耗时,该时钟不依赖于系统时间。因为外部可能会改变系统时间,所以可能会导致偏差。单调时钟只能测量给定点之间的时间,而无法知道“当前时间”。

这个Clock接口提供了一个常规的API去测量时间间隔。MonoClock是实现了Clock的对象;它提供了不同平台上默认的单调时间源。

使用“Clock”接口时,你需要明确动作开始的时间,以及开始后经过的时间。这能满足你在不同方法里调用开始和结束。

measureTimedValue函数可以测试某个操作的耗时,同时结果和耗时都会通过返回值获得。函数内部是通过MonoClock测量方法的耗时。

想了解更多关于Duration类的实现,以及对于不同平台Clock接口和MonoClock实现的详细信息,请查阅 KEEP。请注意这个API目前仍处于试验状态,可能会根据你的反馈而有相应的更改。你需要明确标示注释来使用这些API。

我们非常欢迎你的反馈!

位操作函数

现在标准库包含用于位操作的API(当然,还在测试阶段):

注意已对Int、Long、Short、Byte及其对应的无符号类型添加了类似的扩展函数。

IntelliJ IDEA支持

Java to Kotlin转换器的优化

我们正计划改进Java-to-Kotlin的转换器,以最大程度减少转换后必须手动修复的”异常代码”数量。由于现在的转换器基本都生成为不可空的类型,而使得你需要手动去修改这些可空性问题。这通常都会在运行时由于是否为空的匹配异常而报错。

经过优化的Java-to-Kotlin转换器新版本,将会尝试根据代码中的Java类型用法,而尽可能去推断可空性。不可能生成100%无错误的代码。旨在减少编译错误的数量,并使生成的Kotlin代码更易于修改。新的转换器也修复了许多已知的错误。例如,现在能正确处理隐式Java类型转换了。

新的转换器将在未来成为默认选择。在当前版本中,仅供试用。要开启它,在设置中勾选Use New J2K(experimental)

请尽可能地试用并给予我们反馈!

调试模式的改善

我们改善了Kotlin“变量”的呈现方式。由于字节码中还有很多额外的开发信息,因此Kotlin“变量”界面仅会突显相关变量。若你该版本在lambda(内联或非内联)中设置断点,它将比之前表现得更好。 lambda内部的局部变量以及从外部上下文和外部函数的参数捕获的变量都能清晰显示出来:

debug_lambda_variables

现在你可以根据需要在函数的末尾设置断点了:

end_of_function_breakpoint

对于许多”特殊”的语言特性(例如本地扩展函数或成员扩展属性的访问器),已实现了调试中“Evaluate expression”功能的支持。同样现在你可以通过“Evaluate expression”修改变量了:

img

当然你也可以直接在“变量”界面中修改变量。

新的intentions和inspections

添加了新的intentions和inspections。 其目的是帮助你习惯Kotlin代码的编写方式。 例如,以下intention建议用indices属性代替创建索引范围:

img

如果不使用索引,则可以通过for循环自动遍历元素。

IntelliJ IDEA现状:

  • 可以通过Delegates.notNull()语法自动替换基本类型的lateinit属性。
  • 支持将普通属性转换为懒加载属性返回
  • 检测Java用于数组比较的方法(例如Arrays.equals()Array.deepEquals()),并建议将其替换为与Kotlin对应的方法(例如contentEqualscontentDeepEquals)。
  • 在comletion列表中高亮被标记deprecated的引用。
deprecated_imports

IDE基本操作的性能已经得到优化了,修复了已知会导致UI冻结的几种情况(例如在代码繁复的文件上使用”Move”进行重构)。

Kotlin/JS

这次更新支持在Windows上使用org.jetbrains.kotlin.js插件构建和运行Kotlin / JS Gradle项目。你可以像其他平台一样使用Gradle任务来构建和运行项目,解决并包含Gradle配置中所需的NPM依赖关系,也可以通过webpack-dev-server试运行应用程序(例如通过调用Gradle中的browserRun任务), 还有更多的功能。和其他平台一样,以上无需安装和配置node、npm和yarn的分发就可直接使用。

在看不到的地方,Kotlin/JS还进行了一系列性能改进,缩短了项目的增量编译时间。这意味着最优情况下能比1.3.41快30%。

我们改善对NPM的集成意味着项目现在支持并行和懒加载,并且增加了对同一项目编译之间具有依赖传递的项目的支持。

新版本中所生成组件结构和命名也有所变化。 现在,生成的组件被捆绑在发行文件夹中,其中包括项目的版本号和archiveBaseName(默认为项目名称),例如 projectName-1.0-SNAPSHOT.js

Dukat

Dukat 允许将TypeScript声明文件(.d.ts)自动转换为Kotlin外部声明(代替了ts2kt命令行工具)。 这极大减少了手动编写JS库包装器的需求,这方便于Kotlin以类型安全的方式调用JavaScript生态中的库。

Kotlin/JS现在为Gradle项目的dukat集成提供了实验性支持。运行集成在Gradle的构建任务,可以自动为npm依赖项生成Typesafe包装器,并能直接在Kotlin中使用。

kotlin-dukat-preview

由于dukat还处于早起阶段,因此默认禁用其集成。在项目根目录的gradle.properties文件中增加kotlin.js.experimental.generateKotlinExternals=true配置行,可启用dukat。我们也提供了一个示例项目 ,演示如何在Kotlin/JS项目中使用dukat,请使用并给予我们你的反馈

Kotlin/Native

对于分辨Kotlin/Native与Kotlin的版本并非一件易事。但这个噩梦已然终结, Kotlin和Kotlin/Native的版本现已统一。Kotlin和Kotlin/Native都统一使用1.3.50来命名该发行版本,从而减少了的混乱。

该版本为所有平台(包括macOS和iOS)带来了更多预加载的Apple框架。 Kotlin/Native编译器现会在生成的框架中包含实际的中间码。

互操作性得到了改善。 现在,框架生成支持kotlin.Deprecated注释,并且生成的Objective-C headers code将不会有警告。 getOriginalKotlinClass()函数已添加到标准库,允许从Objective-C类或协议中获取KClass

标准库已更新并支持Kotlin/Native类型的kotlin.reflect.typeOf()函数。 Worker类型增加了新函数executeAfter(),可在指定延迟后执行操作。 另外,您可以在Worker上调用processQueue()函数来显式处理任务队列。

旧函数ByteArray.stringFromUtf8()ByteArray.stringFromUtf8OrThrow()已不推荐使用了。 在之前的版本中,我们添加了ByteArray.decodeToString()函数(在kotlin.text包),以将UTF-8字符串转换为Kotlin字符串。 该函数不支持以NULL终止的字符串,因此,为了解决该问题,在1.3.50中,我们添加了一个新的函数来处理以NULL终止的UTF-8字符串。ByteArray.toKString()函数(位于kotlinx.cinterop包)可用于将以NULL结尾的UTF-8字符串转换为Kotlin字符串。 你可以根据需求传递起始索引和结束索引作为参数。

我们已弃用并删除了kotlin-platform-nativeGradle插件,转而推荐使用kotlin-multiplatformGradle插件,这非常利于你的多平台项目。 查阅文档以获得迁移指南和更多的信息

最后,我们非常高兴能分享该版本中Kotlin/Native编译器和interop工具性能的改善状况。

多平台项目

现在,可以通过调用DSL新增的withJava()函数,将Java编译包含到多平台项目的Kotlin/JVM目标中。 它将默认配置Java插件并使用src / <targetName> Main / java和src / <targetName> Test / java路径。 下面是一个完整的示例,通过启用Java编译来创建Kotlin/JVM目标:

Kotlin的|新建项目向导现可以为新项目生成Gradle Kotlin DSL。

现在也支持在IntelliJ IDEA Ultimate中调试Kotlin/Native代码了! 尝试安装新的IntelliJ IDEA Ultimate的Native调试插件。 它会检测Kotlin/Native运行配置,并支持调试操作:

debugging-kotlin-native-1.3.50

脚本

该版本为脚本和REPL改善了性能并添加了多项特性。 使用Kotlin作为应用程序的脚本语言更加容易! 现在脚本支持开箱即用:我们已经发布了一个默认的JSR-223实现库,因此若要为你的应用程序添加Kotlin脚本支持,只需添加kotlin-scripting-jsr223依赖项并使用 Kotlin的javax.script API。

现在JSR-223 API设置的属性在脚本中可作为常规Kotlin属性进行访问了(在这之前必须使用bindings映射):

在Kotlin1.3版本中为了简化创建和编写基础通用脚本而引入的kotlin-main-kts组件,现在也可以作为JSR-223的头文件。 除去解决依赖关系的诸如RepositoryDependsOn之类的注释外,现在还支持“ @Import”注释,指示脚本编译器将另一个脚本“导入”到当前脚本中:

阅读KEEP-75.以了解更多有关脚本的信息。你可以在Kotlin仓库里获取示例。请在Kotlin Slack的#scripting频道中分享你的反馈!

如何升级

你仍然可以在play.kotl.in在线Kotlin

  • Maven, Gradle, and npm:修改编译器和标准库的版本为1.3.50 。可以在这里查看文档。
  • IntelliJ IDEAAndroid Studio:升级Kotlin插件到1.3.50。打开Tools | Kotlin | Configure Kotlin Plugin Updates点击“Check for updates now”按钮。
  • Eclipse:通过Marketplace安装插件。
  • Github release页面下载命令行编译版本。

如果你在新版本中遇到任何问题,欢迎在Slack的论坛上寻求帮助(在这里),或在问题跟踪器中报告问题。

请尽情享受Kotlin!

外部的贡献者

我们要特别感谢Toshiaki Kameyama正在进行的工作,为IntelliJ IDEA提供许多有用的意图和检查。

我们要感谢所有外部贡献者,他们的PR都包含在这个版本中:

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

发表评论

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