内容简介:Kotlin 1.4 将于 2020 年春季推出,其开发团队在博客介绍了他们对 Kotlin 的愿景:“让 Kotlin 成为您所有工作的可靠伴侣,并是您执行任务的默认语言选择。”因此,开发团队将会让开发者在所有平台上都能使用 Kotlin。据开发团队的介绍,Kotlin 1.4 将侧重于质量和性能。因为对现在的 Kotlin 来说,提高整体体验比添加新功能更加重要。此外,因为构建速度通常是用户最关心的问题,所以开发团队正在不断改进工具链以解决此问题。但是逐步改进跟不上生产代码库的自然增长:尽管开发团队加快
Kotlin 1.4 将于 2020 年春季推出,其开发团队在博客介绍了他们对 Kotlin 的愿景:“让 Kotlin 成为您所有工作的可靠伴侣,并是您执行任务的默认语言选择。”因此,开发团队将会让开发者在所有平台上都能使用 Kotlin。
据开发团队的介绍,Kotlin 1.4 将侧重于质量和性能。因为对现在的 Kotlin 来说,提高整体体验比添加新功能更加重要。此外,因为构建速度通常是用户最关心的问题,所以开发团队正在不断改进 工具 链以解决此问题。但是逐步改进跟不上生产代码库的自然增长:尽管开发团队加快了编译速度,但用户编写了更多的代码,使总体构建时间还不够短。为此,开发团队计划重新实现编译器以使其更快速。
新的编译器
新编译器实现的目标是变得更快速、统一 Kotlin 支持的所有平台,并提供用于编译器扩展的 API。这将是一项多年的工作,不过开发团队已开始好一阵子了,因此新实现的某些部分将在 1.4 中发布,可让这个过程变得更加平顺。
有些功能也已经发布了; 例如,如果开发者尝试了用于类型推理的新算法,它是新编译器的一部分。其他部分的处理方法相同。 也就是说,两种版本都将在一段时间内可用,旧版本和新版本都将处于实验模式; 当新的稳定后,它将成为默认版本。
新的前端(front-end)加速
开发团队期望新编译器提高的速度将来自新的前端实现。
为了提供一些背景信息,可以将编译想成吸收源文件并将其逐步转换为可执行代码的管道。此管道的第一步俗称为编译器的前端。它解析代码和命名、执行类型检查等。此编译器的这一部分也可以在 IDE 中使用,来高亮显示语法错误、导航到定义并搜索项目中的符号用法。这是 kotlinc
如今花费最多时间的步骤,因此开发团队希望使其更快。
当前的实现尚未完成,并且不会在 1.4 中到来。 但是,大多耗时的工作都是由它完成,因此可以预期提速的效果。基准测试(编译 YouTrack 和 Kotlin 编译器本身)表明,新前端的速度约为现有前端快 4.5 倍。
统一的后端和可扩展性
在前端完成对代码的分析之后,后端将生成可执行文件。目前有三个后端:Kotlin / JVM,Kotlin / JS 和 Kotlin / Native。前两个以往是独立编写的,没有代码共享。当启动 Kotlin / Native 时,它是基于围绕 Kotlin 代码内部表示(internal representation)构建的新基础架构的,该功能具有与虚拟机中的字节码类似的功能。
现在,开发团队计划将其他两个后端迁移到同一内部表示。因此,他们将共享许多后端逻辑并拥有统一的管道,以允许对所有目标仅执行一次大多数功能、优化和错误修复。
虽然正逐步迁移到新的后端,可是在 1.4 中,默认情况下不太可能启用它们,但用户将能够选择明确使用它们。
通用的后端基础结构为跨平台编译器扩展打开了大门。可以在这管道中添加一些自定义处理和/或转换,这些处理和转换将自动适用于所有目标。在 1.4 中将不提供用于此类扩展的公开 API(该 API 稍后将被稳定),但开发团队正在与合作伙伴 (其中包括已经构建其编译器插件的 JetPack Compose )紧密合作。
新的语言功能:
Kotlin 1.4 将提供一些新的语言功能。
Kotlin 类的 SAM 转换
社区已要求开发团队引入对 Kotlin 类( KT-7770 )的 SAM 转换的支持。如果仅将一个抽象方法的接口或类预计作为参数,则将 lambda 作为参数传递时,将应用 SAM 转换。然后,编译器自动将 lambda 转换为实现抽象成员函数的类的实例。
SAM 转换当前仅适用于 Java 接口和抽象类。该设计背后的最初想法是针对此类用例明确使用函数类型。然而,事实证明,函数类型和类型别名并不能涵盖所有用例,开发者常常不得不仅在 Java 中保留接口才能对其进行 SAM 转换。
与 Java 不同,Kotlin 不允许使用一种抽象方法对每个接口进行 SAM 转换。开发团队认为,使接口适用于 SAM 转换的意图应该明确。因此,要定义 SAM 接口,开发者需要使用 fun
关键字标记一个接口,以强调它可以用作功能性接口:
fun interface Action { fun run() } fun runAction(a: Action) = a.run() fun main() { runAction { println("Hello, KotlinConf!") } }
请注意,仅在新的类型推断算法中支持传递 lambda 而不是 fun 接口
。
混合命名和位置参数
Kotlin 禁止将带有显式名称的参数(“命名”)和不带名称的常规参数(“位置”)混合使用,除非仅将命名参数放在所有位置参数之后。但是,在一种情况下,这确实很烦人:当所有参数都保持在正确的位置而您想为中间的一个参数指定名称时。Kotlin 1.4 将解决此问题,因此将能够编写如下代码:
fun f(a: Int, b: Int, c: Int) {} fun main() { f(1, b = 2, 3) }
优化的委托属性
开发团队将改进 lazy
属性和其他一些委托属性的编译方式。
通常,委托属性可以访问相应的 KProperty
反射对象。例如,当使用 Delegates.observable
时,可以显示有关已修改属性的信息:
import kotlin.properties.Delegates class MyClass { var myProp: String by Delegates.observable("<no name>") { kProperty, oldValue, newValue -> println("${kProperty.name}: $oldValue -> $newValue") } } fun main() { val user = MyClass() user.myProp = "first" user.myProp = "second" }
为了使之成为可能,Kotlin 编译器会生成一个附加的语法成员属性,即一个存储所有 KProperty
对象的数组,这些对象表示在类内部使用的委托属性:
>>> javap MyClass public final class MyClass { static final kotlin.reflect.KProperty[] $$delegatedProperties; ... }
但是,某些委托属性不会以任何方式使用 KProperty
。对于他们来说,在 $$delegatedProperties
中生成对象是次优的。Kotlin 1.4 版本将优化这种情况。如果委托属性运算符是 inline
,并且未使用 KProperty
参数,则不会生成相应的反射对象。最出色的示例是 lazy
属性。 lazy
属性的 getValue
实现是 inline
,并且不使用 KProperty
参数:
inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
从 Kotlin 1.4 开始,当定义 lazy
属性时,将不会生成相应的 KProperty
实例。如果在类中使用的唯一委托属性是 lazy
属性(以及符合此优化的其他属性),则不会为类生成整个 $$delegatedProperties
数组:
class MyOtherClass { val lazyProp by lazy { 42 } } >>> javap MyOtherClass public final class MyOtherClass { // no longer generated: static final kotlin.reflect.KProperty[] $$delegatedProperties; ... }
尾随逗号
可以在参数列表中的最后一个参数之后放置一个附加的尾随逗号,然后交换行或添加新参数,而不必添加或删除丢失的逗号。
其他主要变化
-
Kotlin 1.3.40 中引入了的有用的
typeof
函数将变得稳定并在所有平台上得到支持。 -
1.3.60 版本博客文章中已经描述了使您可以在
when
内启用break
和continue
的功能。
相关文章:
你真的懂协程吗 ? Kotlin 协程 Coroutine 全解析
从Java 8到Kotlin的Spring Boot应用程序之旅
英文阅读能力提升:
https://blog.jetbrains.com/kotlin/2019/12/what-to-expect-in-kotlin-1-4-and-beyond/
What to Expect in Kotlin 1.4 and Beyond
Posted on December 6, 2019 by Svetlana Isakova
During the keynote at KotlinConf, Andrey highlighted our strategic view on the current areas of focus for the evolution of Kotlin, and our plans for Kotlin 1.4 which will be released some time next year.
Watch the entire keynote below
Our vision is for Kotlin to be a reliable companion for all your endeavors, a default language choice for your tasks. To accomplish this, we’re going to make it shine on all platforms. Multiple case studies from companies well-known in the industry show that we are making good progress in this direction.
Kotlin 1.4 that is going to arrive in spring 2020 will make another step forward for the Kotlin ecosystem.
Focusing on quality
Most of all, Kotlin 1.4 will focus on quality and performance. Kotlin is a modern language that already pioneers many ideas and approaches. We’re going to keep it modern and always evolving. At the moment, however, we believe that Kotlin has reached the stage where improving the overall experience is more important than adding big features. This is why Kotlin 1.4 will deliver only a few small language changes, which are explained in detail below.
We’ve already managed to achieve some impressive results in boosting the performance of IDEs that support Kotlin. The code completion speed has increased substantially compared to previous versions:
Together with the Gradle team, we’ve made Gradle scripts faster. Kotlin 1.3.60, Gradle Import in Android Studio is about 2.5 times as fast and takes about 75% less memory than it did in Kotlin 1.3.10:
What’s more, loading build.gradle.kts
entails almost zero CPU usage! Also, compiling Kotlin/Native in dev mode is becoming up to 2 times as fast with code caching.
We understand that build speed is often the biggest concern for our users, and we are constantly improving our toolchain to address that. But incremental improvements cannot keep up with the natural growth of production codebases: while we make compilation faster, users write more code, and the overall build time doesn’t improve enough. It’s become clear that we need to reimplement the compiler to make it really fast.
New compiler
The goal for the new compiler implementation is to be really fast, unify all the platforms Kotlin supports, and provide an API for compiler extensions. This is going to be a multi-year effort, but we started a while ago, so some parts of this new implementation are going to arrive in 1.4, and the transition will be very gradual. It’s happening already; for instance, if you’ve tried the new algorithm for type inference, that’s a part of the new compiler. The approach for other parts will be the same; that is, both versions will be available for some time, the old one and the new one in an experimental mode; and when the new one becomes stable, it will become the default.
Speed-up with the new front-end
The bulk of the speed-up we expect from the new compiler will come through a new front-end implementation.
To provide a little background, compilation can be thought of as a pipeline that takes source files and turns them into executable code step by step. The first big step in this pipeline is colloquially referred to as the front-end of the compiler. It parses the code, resolves names, performs type checking, etc. This part of the compiler also works inside the IDE when it highlights errors, navigates to definitions, and searches for symbol usages in your project. And this is the step where kotlinc spends the most time nowadays, so we want to make it much faster.
The current implementation is not complete yet, and it will not arrive in 1.4. However, it already does most of the time-consuming work, and we can measure the expected speed-up. Our benchmarks (compiling YouTrack and the Kotlin compiler itself) show that the new front-end will be about 4.5 times as fast as the existing one.
Unified back-ends and extensibility
After the front-end is done analyzing the code, a back-end generates the executables. We have three back-ends: Kotlin/JVM, Kotlin/JS, and Kotlin/Native. The first two were historically written independently and didn’t share much code. When we started Kotlin/Native, it was based on a new infrastructure built around an internal representation (IR) for Kotlin code which serves a function somewhat similar to bytecode in virtual machines. We are now migrating the other two back-ends to the same IR. As a result, we will share a lot of the back-end logic and have a unified pipeline, to allow most features, optimizations, and bugfixes to be done only once for all targets.
We will gradually migrate to the new back-ends, and in 1.4 they are unlikely to be enabled by default, but users will be able to opt into using them explicitly.
A common back-end infrastructure opens the door for multiplatform compiler extensions. One can plug into the pipeline and add some custom processing and/or transformations which will automatically work for all targets. In 1.4 we do not provide a public API for such extensions (the API will be stabilized later), but we are working closely with our partners, including JetPack Compose, who are building their compiler plugins already.
Meet KLib: Kotlin Library Format
To build a multiplatform library in Kotlin and ship it so that clients can depend on it, one needs a distribution format that works equally on any platform. This is why we’re introducing KLib: a library format for Kotlin multiplatform. A KLib file contains serialized IR. Your code may add it as a dependency, and the compiler back-end will pick it up and generate executable code for the given platform. The analogy with bytecode still holds here: one can analyze and transform KLibs much like JVM bytecode. Any transformations done to the serialized IR will affect any platform the KLib will be used for.
In fact, Kotlin/Native has been using the KLibs format to distribute Kotlin native libraries for quite a while, and now we are extending the format to support other back-ends and multiplatform libraries. The format will be experimental in 1.4, and we will work on providing a stable ABI for it in future versions.
More multiplatform news
Running iOS code in Android Studio
We are working on a plugin for Android Studio that will be able to run, test, and debug Kotlin code on iOS devices and simulators. The plugin is using proprietary code from IntelliJ, so it will be closed-source. It will not bring language support for Objective-C or Swift, and some operations such as deployment to AppStore may require running Xcode, but anything you do with Kotlin code will work from Android Studio with the new plugin installed. We expect to open a preview for this plugin in 2020.
Kotlin/Native runtime improvements
Apart from Linux, Windows, macOS, and iOS, Kotlin/Native now works on watchOS and tvOS, so virtually any device can run Kotlin. We are also working on the runtime performance of Kotlin/Native to make iOS Kotlin programs run even faster.
Core libraries
The Kotlin core libraries work on all platforms. This includes kotlin-stdlib which handles all the basic types and collections, kotlinx.coroutines, kotlinx.serialization, and kotlinx.io. The support for dates is really needed in the multiplatform world, and this is what we are working on: experimental Durations have been already added to stdlib, and DateTime support is under way.
Another important addition to Kotlin libraries is Flow which is a coroutine-based implementation of Reactive Streams. Flow is great at processing streams of data, and it’s making use of the power of Kotlin in doing so. Apart from its ergonomics, Flow brings extra speed. On some benchmarks it is almost 2 times as fast as existing popular Reactive Streams implementations.
For library authors
As creating new libraries is vital for the Kotlin ecosystem, we keep improving the experience of library authors. The new library authoring mode will help shape your code in the way that’s best for stable APIs. Also, we are going to release Dokka 1.0 to support docs generation for all platforms.
Multiplatform web
Sharing code across platforms is great for mobile, but it’s also great for Web clients: a lot can be shared with the server and/or with mobile apps. We invest more and more in the Kotlin/JS tooling, and now can do very fast development roundtrips, from changing Kotlin code to seeing results in the browser:
We’ve also improved JS interop so that now you’ll be able to attach an NPM dependency to a Kotlin project and any .d.ts
type definitions will be picked up automatically by the Kotlin toolchain.
The new IR-based back-end will also bring significant improvements in binary sizes. Compiled JS files can become half their current size.
New language features
Kotlin 1.4 will deliver a few new language features.
SAM conversions for Kotlin classes
The community has requested us to introduce support for SAM conversions for Kotlin classes (KT-7770). SAM conversion applies if you pass a lambda as an argument when an interface or a class with only one single abstract method is expected as a parameter. Then the compiler automatically converts the lambda to an instance of the class implementing the abstract member function.
SAM conversions currently only work for Java interfaces and abstract classes. The initial idea behind this design was to use function types explicitly for such use-cases. It turned out, however, that function types and typealiases don’t cover all the use-cases, and people often had to keep an interface in Java only to get a SAM-conversion for it.
Unlike Java, Kotlin will not allow a SAM conversion for every interface with one single abstract method. We believe that an intention to make an interface applicable for SAM conversion should be explicit. Thus, to define a SAM interface, you’ll need to mark an interface with the fun
keyword to emphasize that it can be used as a functional interface:
fun interface Action {
fun run()
}
fun runAction(a: Action) = a.run()
fun main() {
runAction {
println("Hello, KotlinConf!")
}
}
Note that passing a lambda instead of a fun interface
will be supported only in a new type inference algorithm.
Mixing named and positional arguments
Kotlin prohibits mixing arguments with explicit names (“named”) and regular ones without names (“positional”) unless you put named arguments only after all the positional ones. In one case, however, it’s really annoying: when all arguments stay in their correct positions and you want to specify a name for one argument in the middle. Kotlin 1.4 will fix this issue, so you will be able to write code like:
fun f(a: Int, b: Int, c: Int) {}
fun main() {
f(1, b = 2, 3)
}
Optimized delegated properties
We’ll improve the underlying way in which the lazy
property and some other delegated properties are compiled.
Generally, a delegated property can access the corresponding KProperty
reflection object. For instance, when using Delegates.observable
, you can display information about the modified property:
import kotlin.properties.Delegates
class MyClass {
var myProp: String by Delegates.observable("<no name>") {
kProperty, oldValue, newValue ->
println("${kProperty.name}: $oldValue -> $newValue")
}
}
fun main() {
val user = MyClass()
user.myProp = "first"
user.myProp = "second"
}
Target platform: JVM Running on kotlin v. 1.3.70
To make this possible, the Kotlin compiler generates an additional syntactic member property, an array storing all KProperty
objects that represent delegated properties used inside the class:
>>> javap MyClass
public final class MyClass {
static final kotlin.reflect.KProperty[] $$delegatedProperties;
...
}
Some delegated properties, however, don’t use KProperty
in any way. For them, generating an object in $$delegatedProperties
is suboptimal. The Kotlin 1.4 release will optimize such cases. If the delegated property operators are inline
, and the KProperty
parameter is not used, the corresponding reflection objects will not be generated.
The most outstanding example is the lazy
property. The implementation of getValue
for the lazy
property is inline
and doesn’t use the KProperty
parameter:
inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
Starting with Kotlin 1.4, when you define a lazy
property, the corresponding KProperty
instance won’t be generated. If the only delegated properties you use in a class are lazy
properties (and other properties that comply with this optimization), the whole $$delegatedProperties
array won’t be generated for the class:
class MyOtherClass {
val lazyProp by lazy { 42 }
}
>>> javap MyOtherClass
public final class MyOtherClass {
// no longer generated:
static final kotlin.reflect.KProperty[] $$delegatedProperties;
...
}
Trailing Commas
This minor syntactic change turns out to be incredibly convenient! You can place an additional trailing comma after the last parameter in a parameter list. You can then swap lines or add new parameters without having to add or remove the missing commas.
Other notable changes
A useful typeof
function introduced in Kotlin 1.3.40 is going to become stable and supported on all platforms.
The feature that lets you enable break
and continue
inside when
was already described in the 1.3.60 release blog post.
Thank you!
We’re really grateful to everyone who has tried the Kotlin EAPs and experimental features and has given us feedback. We are developing the Kotlin language together with you, and making many design decisions based on your invaluable inputs. Keeping this fast and effective feedback loop going with the community is really important to help Kotlin become the best it can be!
We’re really grateful to all members of our community who are creating so many amazing things with Kotlin. Let’s continue to Kotlin together!
By the way, the Kotlin plugin inside IntelliJ IDEA and Android Studio collects anonymized statistics of your usage of its functionality. We want to kindly ask you to opt into these statistics, as they help us understand what works, what is causing difficulties, and what we should focus on improving.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- WWDC2017看点分析:那些内容值得期待?
- 2019 的 WWDC 发布会,什么值得期待?
- Kotlin 1.4 和未来值得期待的地方
- 2019年的Paint.NET路线图,值得你期待
- WWDC最全围观姿势:除了iOS 11还有什么值得期待?
- Java 11 发布线路图:有哪些值得期待的新特性?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。