Kotlin 1.3 的新特性
Kotlin 1.3 的新特性
協程正式發布
Kotlin 1.3 引入了掛起函數的可調用引用以及在反射API 中對協程的支持。
Kotlin/Native
多平台項目
在1.3 中,我們完全修改了多平台項目的模型,以提高表現力與靈活性,並使共享公共代碼更加容易。此外,多平台項目現在也支持Kotlin/Native!
與舊版模型的主要區別在於:
契約
Kotlin 編譯器會做大量的靜態分析工作,以提供警告並減少模版代碼。其中最顯著的特性之一就是智能轉換——能夠根據類型檢測自動轉換類型。
然而,一旦將這些檢測提取到單獨的函數中,所有智能轉換都立即消失了:
為了改善在此類場景中的行為,Kotlin 1.3引入了稱為契約的實驗性機制。
契約讓一個函數能夠以編譯器理解的方式顯式描述其行為。目前支持兩大類場景:
- 通過聲明函數調用的結果與所傳參數值之間的關係來改進智能轉換分析:
- 在存在高階函數的情況下改進變量初始化的分析:
標準庫中的契約
stdlib
(kotlin標準庫)已經利用契約帶來瞭如上所述的對代碼分析的改進。這部分契約是穩定版的,這意味著你現在就可以從改進的代碼分析中受益,而無需任何額外的opt-ins:
Target platform: JVM Running on kotlin v. 1.3.11
stdlib
(kotlin標準庫)已經利用契約帶來瞭如上所述的對代碼分析的改進。這部分契約是穩定版的,這意味著你現在就可以從改進的代碼分析中受益,而無需任何額外的opt-ins:
Target platform: JVM Running on kotlin v. 1.3.11
自定義契約
可以為自己的函數聲明契約,不過這個特性是實驗性的,因為目前的語法尚處於早期原型狀態,並且很可能還會更改。另外還要注意,目前Kotlin編譯器並不會驗證契約,因此程序員有責任編寫正確合理的契約。
通過調用標準庫(stdlib)函數contract
來引入自定義契約,該函數提供了DSL作用域:
contract
來引入自定義契約,該函數提供了DSL作用域:
將when
主語捕獲到變量中
在Kotlin 1.3中,可以將when
表達式主語捕獲到變量中:
when
表達式主語捕獲到變量中:接口中伴生對象的@JvmStatic 與@JvmField
對於Kotlin 1.3,可以使用註解@JvmStatic
與@JvmField
標記接口的companion
對象成員。在類文件中會將這些成員提升到相應接口中並標記為static
。
例如,以下Kotlin 代碼:
相當於這段Java 代碼:
@JvmStatic
與@JvmField
標記接口的companion
對象成員。在類文件中會將這些成員提升到相應接口中並標記為static
。註解類中的內嵌聲明
在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
main(args: Array)
的函數,其中args
表示傳給該程序的命令行參數。然而,並非每個應用程序都支持命令行參數,因此這個參數往往到最後都沒有用到。main
形式。現在Kotlin版的Hello,World
縮短了19個字符!
Target platform: JVM Running on kotlin v. 1.3.11
更多元的函數
在Kotlin中用帶有不同數量參數的泛型類來表示函數類型:Function0
、Function1
、Function2
……這種方式有一個問題是這個列表是有限的,目前只到Function22
。
Kotlin 1.3 放寬了這一限制,並添加了對具有更多元數(參數個數)的函數的支持:
Function0
、Function1
、Function2
……這種方式有一個問題是這個列表是有限的,目前只到Function22
。漸進模式
Kotlin 非常注重代碼的穩定性與向後兼容性:Kotlin 兼容性策略提到“破壞性變更”(例如,會使以前編譯正常的代碼現在不能通過編譯的變更)只能在主版本(1.2、1.3等)中引入。
我們相信很多用戶可以使用更快的周期,其中關鍵的編譯器修復會即時生效,從而使代碼更安全、更正確。因此Kotlin 1.3引入了漸進編譯器模式,可以通過將參數-progressive
傳給編譯器來啟用。
在漸進模式下,語言語義中的一些修復可以即時生效。所有這些修復都有以下兩個重要特徵:
- 保留了源代碼與舊版編譯器的向後兼容性,這意味著可以通過非漸進式編譯器編譯所有可由漸進式編譯器編譯的代碼。
- 只是在某種意義上使代碼更安全 ——例如,可以禁用某些不安全的智能轉換,可以將所生成代碼的行為更改為更可預測、更穩定,等等。
啟用漸進模式可能需要重寫一些代碼,但不會太多——所有在漸進模式啟用的修復都已經過精心挑選、通過審核並提供遷移輔助工具。我們希望對於任何積極維護、即將快速更新到最新語言版本的代碼庫來說,漸進模式都是一個不錯的選擇。
-progressive
傳給編譯器來啟用。內聯類
Kotlin 1.3引入了一種新的聲明方式—— inline class
。內聯類可以看作是普通類的受限版,尤其是內聯類必須有且只有一個屬性:
Kotlin 編譯器會使用此限制來積極優化內聯類的運行時表示,並使用底層屬性的值替換內聯類的實例,其中可能會移除構造函數調用、GC 壓力,以及啟用其他優化:
Target platform: JVM Running on kotlin v. 1.3.11
inline class
。內聯類可以看作是普通類的受限版,尤其是內聯類必須有且只有一個屬性:
Target platform: JVM Running on kotlin v. 1.3.11
無符號整型
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
kotlin.UByte
: 無符號8 比特整數,範圍是0 到255kotlin.UShort
: 無符號16 比特整數,範圍是0 到65535kotlin.UInt
: 無符號32 比特整數,範圍是0 到2^32 - 1kotlin.ULong
: 無符號64 比特整數,範圍是0 到2^64 - 1
Target platform: JVM Running on kotlin v. 1.3.11
@JvmDefault
Kotlin兼容很多Java版本,其中包括不支持默認方法的Java 6與Java 7。為了方便起見,Kotlin編譯器可以變通突破這個限制,不過這個變通方法與Java 8引入的default
方法並不兼容。
這可能會是Java互操作性的一個問題,因此Kotlin 1.3引入了@JvmDefault
註解。以此註解標註的方法會生成為JVM平台的default
方法:
default
方法並不兼容。@JvmDefault
註解。以此註解標註的方法會生成為JVM平台的default
方法:標準庫
多平台 Random
在Kotlin 1.3之前沒有在所有平台生成隨機數的統一方式——我們不得不借助平台相關的解決方案,如JVM平台的java.util.Random
。這個版本通過引入在所有平台都可用的kotlin.random.Random
類來解決這一問題。
Target platform: JVM Running on kotlin v. 1.3.11
java.util.Random
。這個版本通過引入在所有平台都可用的kotlin.random.Random
類來解決這一問題。
Target platform: JVM Running on kotlin v. 1.3.11
isNullOrEmpty 與orEmpty 擴展
一些類型的isNullOrEmpty
與orEmpty
擴展已經存在於標準庫中。如果接收者是null
或空容器,第一個函數返回true
;而如果接收者是null
,第二個函數回退為空容器實例。Kotlin 1.3為集合、映射以及對像數組提供了類似的擴展。
isNullOrEmpty
與orEmpty
擴展已經存在於標準庫中。如果接收者是null
或空容器,第一個函數返回true
;而如果接收者是null
,第二個函數回退為空容器實例。Kotlin 1.3為集合、映射以及對像數組提供了類似的擴展。在兩個現有數組間複製元素
為包括無符號整型數組在內的現有數組類型新增的函數array.copyInto(targetArray, targetOffset, startIndex, endIndex)
使在純Kotlin中實現基於數組的容器更容易。
Target platform: JVM Running on kotlin v. 1.3.11
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
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
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
。
kotlin-reflect
中添加了一個新的API,可以列出密封(sealed
)類的所有直接子類型,即KClass.sealedSubclasses
。小改動
Boolean
類型現在有伴生對象了。
Any?.hashCode()
擴展函數對null
返回0。
Char
現在提供了MIN_VALUE
/ MAX_VALUE
常量。
- 原生類型伴生對像中的常量
SIZE_BYTES
與 SIZE_BITS
。
Boolean
類型現在有伴生對象了。Any?.hashCode()
擴展函數對null
返回0。Char
現在提供了MIN_VALUE
/ MAX_VALUE
常量。SIZE_BYTES
與 SIZE_BITS
。工具
IDE 中的代碼風格支持
kotlinx.serialization
kotlinx.serialization是一個在Kotlin中為(反)序列化對象提供多平台支持的庫。以前,它是一個獨立項目,不過自Kotlin 1.3起,它與其他編譯器插件一樣隨Kotlin編譯器發行版一起發行。其主要區別在於,無需人為關注序列化IDE插件與正在使用的Kotlin IDE插件是否兼容了:現在Kotlin IDE插件已經包含了序列化支持!
請注意,儘管kotlinx.serialization現在隨Kotlin編譯器發行版一起發行,但它仍是一個實驗性的特性。
請注意,儘管kotlinx.serialization現在隨Kotlin編譯器發行版一起發行,但它仍是一個實驗性的特性。
腳本更新
請注意,腳本支持是一項實驗性的特性,這意味著不會對API提供兼容性保證。
Kotlin 1.3 繼續發展與改進腳本API,為腳本定制引入了一些實驗性支持,例如添加外部屬性、提供靜態或動態依賴等等。
請注意,腳本支持是一項實驗性的特性,這意味著不會對API提供兼容性保證。