出品|開源中國
作者|羅奇奇
11 月 16 日,JetBrains釋出了 Kotlin 1。6。0 ,其中包含穩定的詳盡
whens
宣告、Kover 和 Kotlin/Native 的新記憶體管理器,1。5。30 中釋出的其他語言和標準庫功能也變得更穩定。
密封(詳盡)
Sealed
when
是一項期待已久的功能,如果你的 when 語句不夠詳盡,Kotlin 編譯器發會警告。
Kotlin 會詳盡地檢查封閉類、列舉和布林型別的表示式,使用那些代數資料型別對域建模時它非常有用。例如對應用程式的使用者有不同的契約首選項,建模為一個封閉的類層次結構:
sealed class Contact { data class PhoneCall(val number: String) : Contact() data class TextMessage(val number: String) : Contact() data class InstantMessage(val type: IMType, val user: String) : Contact() }
現在,如果你寫了一個表示式:根據不同的聯絡人偏好返回不同的結果。但是又忘記處理應用程式中的所有型別,編譯器將會標記一個錯誤:
fun Rates。computeMessageCost(contact: Contact): Cost = when (contact) { // ERROR: ‘when’ expression must be exhaustive is Contact。PhoneCall -> phoneCallCost is Contact。TextMessage -> textMessageCost }
在 Kotlin 1。6。0 之前,這種問題編譯器只會報弱 IDE 檢查,從 Kotlin 1。6 開始,它會產生以下編譯器警告(warning):
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.
在 Kotlin 1。7 中它會變成一個錯誤(ERROR),詳情可參閱KT-47709。
Suspending 函式作為超型別
Kotlin 1。6 穩定了對將
suspend
掛起函式型別實現為超級介面的功能。
設計 Kotlin API 需要自定義各種庫函式的行為時,接受函式型別是慣用的做法。例如,
kotlinx.coroutines
API 在其 Job 介面中有一個成員函式,看起來類似於:
fun invokeOnCompletion(handler: () -> Unit)
可以方便地使用像
invokeOnCompletion
這些 lambda 函式。如果想要處理完成的類,可以透過在類中直接實現函式 type () -> 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 穩定了從常規到掛起函式型別的轉換。現在可以傳遞任何常規函式型別的表示式,其中使用預期掛起作為引數,編譯器將自動執行轉換。
改進了遞迴泛型型別的型別推斷
從1。6。0開始,如果預設情況下是遞迴泛型,Kotlin編譯器能根據相應型別形參的上限推斷型別實參。這可以實現使用遞迴泛型型別建立各種模式(通常在 Java 中用於製作構建器 API):
// Before 1。5。30 val containerA = PostgreSQLContainer(DockerImageName。parse(“postgres:13-alpine”))。apply { withDatabaseName(“db”) withUsername(“user”) withPassword(“password”) withInitScript(“sql/schema。sql”) } // With compiler option in 1。5。30 or by default starting with 1。6。0 val containerB = PostgreSQLContainer(DockerImageName。parse(“postgres:13-alpine”)) 。withDatabaseName(“db”) 。withUsername(“user”) 。withPassword(“password”) 。withInitScript(“sql/schema。sql”)
Builder inference 改進
Kotlin 1。5。30 引入了
-Xunrestricted-builder-inference
編譯器選項,讓關於構建器呼叫的型別資訊可以在構建器 lambda 中獲取。也就是說,它引入了呼叫返回尚未推斷型別的例項的能力,比如 buildList() lambda 中的
get()
。
從 1。6。0 開始,無需指定
-Xunrestricted-builder-inference
進行以前禁止的呼叫。現在可以使用-Xenable-builder-inference 編譯器選項編寫自己的泛型構建器,而不需要應用
@BuilderInference
註釋,且如果常規型別推斷無法解析型別資訊,你還可以自動啟用 Builder inference構建器推斷。
長期支援以前的 API 版本
從 Kotlin 1。6。0 開始可以使用三個以前的 API 版本進行開發,目前可用的 API 版本包括 1。3、1。4、1。5 和 1。6。
Kotlin/JVM
具有執行時保留的可重複註釋。
Kotlin 與Java 8 一樣具有可重複的註釋。在 Kotlin 1。6 中,該功能與 Java 相容,
@kotlin.annotation.Repeatable
現在接受任何保留並讓註釋在 Kotlin 和 Java 中都可重複。
Kotlin 端現在也支援 Java 可重複註釋。
Kotlin/Native
現在可以嘗試
新 Kotlin/Native 記憶體管理器
的實驗版。此功能致力於在多平臺專案中提供一致的開發體驗。新的記憶體管理器解除了對執行緒間物件共享的現有限制,並提供完全無洩漏的併發程式設計原語,這些原語是安全的,不需要開發人員進行任何特殊管理或註釋。
Kotlin/Native 現在支援 Xcode 13。
在任何主機上編譯 Windows 目標,
現在可以在任何支援 Kotlin/Native 的主機上編譯 Windows 目標
mingwX64
和
mingwX86
。
Kotlin 1。6。0
重新設計了
Kotlin/Native 在幕後使用
的 LLVM 依賴項,
同時將 LLVM 版本更新到 11。1。0 ,並減少了依賴項大小。
帶有 JVM 和 JS IR 後端的統一編譯器外掛 ABI
。現在,Kotlin 多平臺 Gradle 外掛能夠將可嵌入的編譯器 jar(用於 JVM 和 JS IR 後端的那個)用於 Kotlin/Native,這意味著可以為 Native 和其他支援的平臺使用相同的編譯器外掛工件。
穩定的
Kotlin 1。6。0 帶來了穩定的
typeOf()
。從 1。3。40 開始,
typeOf()
作為實驗性 API 在 JVM 平臺上可用,現在可以在任何 Kotlin 平臺上使用它,且
KType
編譯器可以推斷任何 Kotlin 型別的表示。
inline fun renderType(): String { val type = typeOf() return type。toString() } fun main() { val fromExplicitType = typeOf() val fromReifiedType = renderType>() }
穩定的集合構建器
buildMap()
,
buildList()
和
buildSet()
已經穩定,構建器返回的集合現在可以在只讀狀態下序列化。
穩定的整數位旋轉操作
將數字的二進位制表示式向左或向右旋轉指定位數的
rotateLeft()
和
rotateRight()
函式已經穩定。
val number: Short = 0b10001 println(number。rotateRight(2)。toString(radix = 2)) // 100000000000100 println(number。rotateLeft(2)。toString(radix = 2)) // 1000100
穩定正則表示式函式
穩定了
splitToSequence()
——一個用於將字串拆分為序列的正則表示式函式
val colorsText = “green, red , brown&blue, orange, pink&green” val regex = “[,\\\\\\\\s]+”。toRegex() val mixedColor = regex。splitToSequence(colorsText) 。onEach { println(it) } 。firstOrNull { it。contains(‘&’) } println(mixedColor) // “brown&blue”
有關 Kotlin 1。6。0 的詳盡資訊可在釋出公告中檢視。