Kotlin 1.3 的新特性


Kotlin 1.3 的新特性

協程正式發布

歷經了漫長而充足的的測試,協程終於正式發布了!這意味著自Kotlin 1.3起,協程的語言支持與API已完全穩定參見新版協程概述
Kotlin 1.3 引入了掛起函數的可調用引用以及在反射API 中對協程的支持。

Kotlin/Native

Kotlin 1.3繼續改進與完善原生平台。詳情請參見Kotlin/Native概述

多平台項目

在1.3 中,我們完全修改了多平台項目的模型,以提高表現力與靈活性,並使共享公共代碼更加容易。此外,多平台項目現在也支持Kotlin/Native!
與舊版模型的主要區別在於:
  • 在舊版模型中,需要將公共代碼與平台相關代碼分別放在獨立的模塊中,以expectedBy依賴項鍊接。現在,公共代碼與平台相關代碼放在相同模塊的不同源根(source root)中,使項目更易於配置。
  • 對於不同的已支持平台,現在有大量的預設的平台配置
  • 更改了依賴配置;現在為每個源根分別指定依賴項。
  • 源集(source set)現在可以在任意平台子集之間共享(例如,在一個目標平台為JS、Android 與iOS 的模塊中,可以有一個只在Android 與iOS 之間共享的源集)。
  • 現在支持發布多平台庫了。
更多相關信息,請參考多平台程序設計文檔

契約

Kotlin 編譯器會做大量的靜態分析工作,以提供警告並減少模版代碼。其中最顯著的特性之一就是智能轉換——能夠根據類型檢測自動轉換類型。
然而,一旦將這些檢測提取到單獨的函數中,所有智能轉換都立即消失了:
為了改善在此類場景中的行為,Kotlin 1.3引入了稱為契約的實驗性機制。
契約讓一個函數能夠以編譯器理解的方式顯式描述其行為。目前支持兩大類場景:
  • 通過聲明函數調用的結果與所傳參數值之間的關係來改進智能轉換分析:
  • 在存在高階函數的情況下改進變量初始化的分析:

標準庫中的契約

stdlib(kotlin標準庫)已經利用契約帶來瞭如上所述的對代碼分析的改進。這部分契約是穩定版的,這意味著你現在就可以從改進的代碼分析中受益,而無需任何額外的opt-ins:
Target platform: JVM Running on kotlin v. 1.3.11

自定義契約

可以為自己的函數聲明契約,不過這個特性是實驗性的,因為目前的語法尚處於早期原型狀態,並且很可能還會更改。另外還要注意,目前Kotlin編譯器並不會驗證契約,因此程序員有責任編寫正確合理的契約。
通過調用標準庫(stdlib)函數contract來引入自定義契約,該函數提供了DSL作用域:
請參見KEEP中關於語法與兼容性注意事項的詳細信息。

when主語捕獲到變量中

在Kotlin 1.3中,可以將when表達式主語捕獲到變量中:
雖然已經可以在when表達式前面提取這個變量,但是在when中的val使其作用域剛好限制在when主體中,從而防止命名空間污染。關於when表達式的完整文檔請參見這裡

接口中伴生對象的@JvmStatic 與@JvmField

對於Kotlin 1.3,可以使用註解@JvmStatic@JvmField標記接口的companion對象成員。在類文件中會將這些成員提升到相應接口中並標記為static
例如,以下Kotlin 代碼:
相當於這段Java 代碼:

註解類中的內嵌聲明

在Kotlin 1.3 中,註解可以有內嵌的類、接口、對象與伴生對象:

無參的 main

按照慣例,Kotlin程序的入口點是一個簽名類似於main(args: Array)的函數,其中args表示傳給該程序的命令行參數。然而,並非每個應用程序都支持命令行參數,因此這個參數往往到最後都沒有用到。
Kotlin 1.3引入了一種更簡單的無參main形式。現在Kotlin版的Hello,World縮短了19個字符!
Target platform: JVM Running on kotlin v. 1.3.11

更多元的函數

在Kotlin中用帶有不同數量參數的泛型類來表示函數類型:Function0Function1Function2……這種方式有一個問題是這個列表是有限的,目前只到Function22
Kotlin 1.3 放寬了這一限制,並添加了對具有更多元數(參數個數)的函數的支持:

漸進模式

Kotlin 非常注重代碼的穩定性與向後兼容性:Kotlin 兼容性策略提到“破壞性變更”(例如,會使以前編譯正常的代碼現在不能通過編譯的變更)只能在主版本(1.2、1.3等)中引入。
我們相信很多用戶可以使用更快的周期,其中關鍵的編譯器修復會即時生效,從而使代碼更安全、更正確。因此Kotlin 1.3引入了漸進編譯器模式,可以通過將參數-progressive傳給編譯器來啟用。
在漸進模式下,語言語義中的一些修復可以即時生效。所有這些修復都有以下兩個重要特徵:
  • 保留了源代碼與舊版編譯器的向後兼容性,這意味著可以通過非漸進式編譯器編譯所有可由漸進式編譯器編譯的代碼。
  • 只是在某種意義上使代碼更安全 ——例如,可以禁用某些不安全的智能轉換,可以將所生成代碼的行為更改為更可預測、更穩定,等等。
啟用漸進模式可能需要重寫一些代碼,但不會太多——所有在漸進模式啟用的修復都已經過精心挑選、通過審核並提供遷移輔助工具。我們希望對於任何積極維護、即將快速更新到最新語言版本的代碼庫來說,漸進模式都是一個不錯的選擇。

內聯類

內聯類在Kotlin 1.3起才可用,並且目前是實驗性的。詳見其參考文檔
Kotlin 1.3引入了一種新的聲明方式—— inline class內聯類可以看作是普通類的受限版,尤其是內聯類必須有且只有一個屬性:
Kotlin 編譯器會使用此限制來積極優化內聯類的運行時表示,並使用底層屬性的值替換內聯類的實例,其中可能會移除構造函數調用、GC 壓力,以及啟用其他優化:
Target platform: JVM Running on kotlin v. 1.3.11
詳見內聯類的參考文檔

無符號整型

無符號整數僅在Kotlin 1.3起才可用,並且目前是實驗性的。詳見其參考文檔
Kotlin 1.3 引入了無符號整型類型:
  • kotlin.UByte: 無符號8 比特整數,範圍是0 到255
  • kotlin.UShort: 無符號16 比特整數,範圍是0 到65535
  • kotlin.UInt: 無符號32 比特整數,範圍是0 到2^32 - 1
  • kotlin.ULong: 無符號64 比特整數,範圍是0 到2^64 - 1
無符號類型也支持其對應有符號類型的大多數操作:
Target platform: JVM Running on kotlin v. 1.3.11
詳見其參考文檔

@JvmDefault

@JvmDefault僅在Kotlin 1.3起才可用,並且目前是實驗性的。詳見其參考文檔頁
Kotlin兼容很多Java版本,其中包括不支持默認方法的Java 6與Java 7。為了方便起見,Kotlin編譯器可以變通突破這個限制,不過這個變通方法與Java 8引入的default方法並不兼容。
這可能會是Java互操作性的一個問題,因此Kotlin 1.3引入了@JvmDefault註解。以此註解標註的方法會生成為JVM平台的default方法:
警告!@JvmDefault註解標註的API會對二進制兼容性產生嚴重影響。在生產中使用@JvmDefault之前,請務必仔細閱讀其參考文檔頁

標準庫

多平台 Random

在Kotlin 1.3之前沒有在所有平台生成隨機數的統一方式——我們不得不借助平台相關的解決方案,如JVM平台的java.util.Random這個版本通過引入在所有平台都可用的kotlin.random.Random類來解決這一問題。
Target platform: JVM Running on kotlin v. 1.3.11

isNullOrEmpty 與orEmpty 擴展

一些類型的isNullOrEmptyorEmpty擴展已經存在於標準庫中。如果接收者是null或空容器,第一個函數返回true;而如果接收者是null,第二個函數回退為空容器實例。Kotlin 1.3為集合、映射以及對像數組提供了類似的擴展。

在兩個現有數組間複製元素

為包括無符號整型數組在內的現有數組類型新增的函數array.copyInto(targetArray, targetOffset, startIndex, endIndex)使在純Kotlin中實現基於數組的容器更容易。
Target platform: JVM Running on kotlin v. 1.3.11

associateWith

一個很常見的情況是,有一個鍵的列表,希望通過將其中的每個鍵與某個值相關聯來構建映射。以前可以通過associate { it to getValue(it) }函數來實現,不過現在我們引入了一種更高效、更易讀的替代方式:keys.associateWith { getValue(it) }
Target platform: JVM Running on kotlin v. 1.3.11

ifEmpty 與ifBlank 函數

集合、映射、對像數組、字符序列以及序列現在都有一個ifEmpty函數,它可以指定一個備用值,當接收者為空容器時以該值代替接收者使用:
Target platform: JVM Running on kotlin v. 1.3.11
此外,字符序列與字符串還有一個ifBlank擴展,它與ifEmpty類似,只是會檢測字符串是否全部都是空白符而不只是空串。
Target platform: JVM Running on kotlin v. 1.3.11

反射中的密封類

我們在kotlin-reflect中添加了一個新的API,可以列出密封(sealed)類的所有直接子類型,即KClass.sealedSubclasses

小改動

  • Boolean 類型現在有伴生對象了。
  • Any?.hashCode()擴展函數對null返回0。
  • Char現在提供了MIN_VALUEMAX_VALUE常量。
  • 原生類型伴生對像中的常量SIZE_BYTES與 SIZE_BITS

工具

IDE 中的代碼風格支持

Kotlin 1.3在IDE中引入了對推薦代碼風格的支持。其遷移指南參見這裡

kotlinx.serialization

kotlinx.serialization是一個在Kotlin中為(反)序列化對象提供多平台支持的庫。以前,它是一個獨立項目,不過自Kotlin 1.3起,它與其他編譯器插件一樣隨Kotlin編譯器發行版一起發行。其主要區別在於,無需人為關注序列化IDE插件與正在使用的Kotlin IDE插件是否兼容了:現在Kotlin IDE插件已經包含了序列化支持!
詳見這裡
請注意,儘管kotlinx.serialization現在隨Kotlin編譯器發行版一起發行,但它仍是一個實驗性的特性。

腳本更新

請注意,腳本支持是一項實驗性的特性,這意味著不會對API提供兼容性保證。
Kotlin 1.3 繼續發展與改進腳本API,為腳本定制引入了一些實驗性支持,例如添加外部屬性、提供靜態或動態依賴等等。
關於其他細節,請參考KEEP-75

草稿文件支持

Kotlin 1.3引入了對可運行的草稿文件(scratch files)的支持。草稿文件是一個擴展名為.kts的kotlin腳本文件,可以在編輯器中直接運行並獲取求值結果。
更多細節請參考通用草稿文件文檔
參考資料,google 繁體中文機器翻譯:https://kotlinlang.org/docs/reference/whatsnew13.html