- 1:语言功能
- 1.1:密封when语句
- 1.2:将挂起函数作为父类型
- 1.3:挂起转换
- 2:标准库改动
- 2.1:标准输入的新函数
- 2.2:稳定版 Duration API
- 2.3:稳定版 typeOf()
- 3:在Android Studio中使用Kotlin 1.6.10
去年年底,Kotlin 1.6.0 发布,并带来了稳定版详尽 whens
、Kover 和新版 Kotlin/Native 内存管理器。 1.5.30 版本中发布的其他语言和标准库功能也已达到稳定版。
语言功能
密封when语句
对于密封类、枚举和布尔类型,Kotlin 一直可以详尽地检查 when表达式。 这在使用这些代数数据类型进行领域建模时非常实用。 例如,对于建模为密封类层次结构的应用:
sealed class Contact {
data class PhoneCall(val number: String) : Contact()
data class TextMessage(val number: String) : Contact()
data class InstantMessage(val type: String, val user: String) : Contact()
}
在之前的版本中,如果编写的表达式是根据不同的联系偏好返回不同的结果,那么,在忘记处理应用中的全部类型时,编译器将标记错误:
when(contact){
//错误:when表达式必须详尽
is Contact.TextMessage->{}
is Contact.InstantMessage->{}
}
但是在 Kotlin 1.6 之前,以下使用 when语句的代码即便完全忘记处理通过即时通讯向用户发送通知,也能够成功编译。此时仅仅会报告并不醒目的 IDE 检查,而编译器不会提供任何消息。 从 Kotlin 1.6 开始,会生成以下编译器警告:
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is PhoneCall' branch or 'else' branch instead.
在 Kotlin 1.7 中,警告将成为错误,以避免任何被意外遗漏的机会。
将挂起函数作为父类型
Kotlin 1.6 已稳定支持将 suspend 函数类型实现为父接口。 这是 Kotlin 协同程序设计中缺失的部分之一。 在设计 Kotlin API 中需要自定义各种库函数的行为时,很自然会想到接受函数类型。 例如,kotlinx.coroutines API 的 Job 接口中具有类似于下例的成员函数:
fun invokeOnCompletion(handler: () -> Unit)
可以方便地将此函数与 lambda(例如 invokeOnCompletion { doSomething() })搭配使用。 如果有一个类要处理补全,则可以在类中直接实现函数类型 () -> Unit 来简化和优化代码,无需创建额外的 lambda:
class MyCompletionHandler : () -> Unit {
override fun invoke() { doSomething() }
}
自 Kotlin 1.6 开始,这种优化可以通过挂起函数实现。 如果 API 接受挂起函数类型,如下所示:
public fun launchOnClick(action: suspend () -> Unit) {}
那么将不再受限于只能将 lambda 和挂起函数引用传递至此代码。 也可以在类中实现相应的挂起函数类型:
class MyClickAction : suspend () -> Unit {
override suspend fun invoke() { doSomething() }
}
挂起转换
Kotlin 1.6 已稳定支持将常规函数转换为挂起函数类型。 可以在以挂起函数为形参的方法中传递任何合适的常规函数类型的表达式。 编译器将自动执行转换。
fun process(item:Item){
//do something
}
suspend fun suspendProcess(item: (Item)->Unit){
}
suspendProcess { process(it) }
将process函数的引用传递至suspendProcess调用达到同样的效果会更加方便:
suspendProcess(::process)
将处理函数的引用提取到变量中,便于自定义代码中的行为。 但是,这在 1.6 版本之前的 Kotlin 中无效。 这是因为有一个作为挂起类型的形参传递的常规函数:
val processingFunction = ::process
suspendProcess(processingFunction)
在 Kotlin 1.6 中,上面的代码可以顺利编译和工作。
标准库改动
Kotlin 1.6.0 通过在 readLine() 之后去除 !!、稳定 typeOf() 和提供稳定版 Duration API 完成了三个 stdlib 路线图条目。 它还将以下 stdlib 函数提升到了稳定版:
- 集合构建器
- 整数的位旋转运算
- 用于将字符串拆分为序列的正则表达式函数
标准输入的新函数
在 Kotlin 1.6.0 中,从标准输入读取一行后不再需要使用非 null 断言运算符 !!,这将改善新手体验并简化 Kotlin 教学。为从控制台读取提供了新函数,流程如下:
- readln() 在到达 EOF 时抛出异常。 使用此函数替换以 !! 运算符检查 readLine() 的结果是否为 null。
- 新的 readlnOrNull() 是返回 null 的替代方案。 其行为与先前的 readLine() 相同,但具有代表性更强的名称。
fun main() {
println("Input two integer numbers each on a separate line")
val num1 = readln().toInt()
val num2 = readln().toInt()
println("The sum of $num1 and $num2 is ${num1 + num2}")
}
稳定版 Duration API
除了更易读的 Duration.toString() 输出以及用于从 String 解析 Duration 的新函数(可在 1.5.30 中预览)之外,Duration API 还具有以下变更:
- toComponents 函数的 days 组件现在具有 Long 类型而不是 Int ,避免截断值。
- DurationUnit 枚举现在不是类型别名。 没有将它用作 JVM 上 java.util.concurrent.TimeUnit 的类型别名的情况。
- 为回应社区反馈,将恢复 Int.seconds 等扩展属性。 为限制其适用性,它们仅在 Duration 类的 Companion 中可用。
val duration = 5000.seconds
println("There are ${duration.inWholeMinutes} minutes in ${duration.inWholeHours} hours")
稳定版 typeOf()
Kotlin 1.6.0 带来了稳定版typeOf() 并关闭了相应的路线图条目。 自 1.3.40 起,typeOf() 作为实验性 API 在 JVM 平台上推出,现已可用于所有 Kotlin 平台,可以获得编译器可推断的任何 Kotlin 类型的 KType 表示。
inline fun <reified T> renderType(): String {
val type = typeOf<T>()
return type.toString()
}
fun main() {
val fromExplicitType = typeOf<Int>()
val fromReifiedType = renderType<List<Int>>()
}
在Android Studio中使用Kotlin 1.6.10
1.将Android Studio升级到最新的版本后,在Preferences->Languages & Frameworks->Kotlin更新最新的插件。
2.修改项目根目录下的build.gradle中的Kotlin版本:ext.kotlin_version = "1.6.10"