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關鍵字標記一個接口,以強調它可以用作功能性接口:
funinterfaceAction{
funrun()
}
funrunAction(a:Action)=a.run()
funmain(){
runAction{
println("Hello,KotlinConf!")
}
}
請注意,僅在新的類型推斷算法中支持傳遞 lambda 而不是fun 接口。
混合命名和位置參數
Kotlin 禁止將帶有顯式名稱的參數(“命名”)和不帶名稱的常規參數(“位置”)混合使用,除非僅將命名參數放在所有位置參數之后。但是,在一種情況下,這確實很煩人:當所有參數都保持在正確的位置而您想為中間的一個參數指定名稱時。Kotlin 1.4 將解決此問題,因此您將能夠編寫如下代碼:
funf(a:Int,b:Int,c:Int){}
funmain(){
f(1,b=2,3)
}
優化的委托屬性
開發團隊將改進lazy屬性和其他一些委托屬性的編譯方式。
通常,委托屬性可以訪問相應的KProperty反射對象。例如,當使用Delegates.observable時,可以顯示有關已修改屬性的信息:
importkotlin.properties.Delegates
classMyClass{
varmyProp:StringbyDelegates.observable("
kProperty,oldValue,newValue->
println("${kProperty.name}:$oldValue->$newValue")
}
}
funmain(){
valuser=MyClass()
user.myProp="first"
user.myProp="second"
}
為了使之成為可能,Kotlin 編譯器會生成一個附加的語法成員屬性,即一個存儲所有KProperty對象的數組,這些對象表示在類內部使用的委托屬性:
>>>javapMyClass
publicfinalclassMyClass{
staticfinalkotlin.reflect.KProperty[]$$delegatedProperties;
...
}
但是,某些委托屬性不會以任何方式使用KProperty。對于他們來說,在$$delegatedProperties中生成對象是次優的。Kotlin 1.4 版本將優化這種情況。如果委托屬性運算符是inline,并且未使用KProperty參數,則不會生成相應的反射對象。最出色的示例是lazy屬性。lazy屬性的getValue實現是inline,并且不使用KProperty參數:
inlineoperatorfun
從 Kotlin 1.4 開始,當您定義lazy屬性時,將不會生成相應的KProperty實例。如果您在類中使用的唯一委托屬性是lazy屬性(以及符合此優化的其他屬性),則不會為類生成整個$$delegatedProperties數組:
classMyOtherClass{
vallazyPropbylazy{42}
}
>>>javapMyOtherClass
publicfinalclassMyOtherClass{
//nolongergenerated:
staticfinalkotlin.reflect.KProperty[]$$delegatedProperties;
...
}
尾隨逗號
這個微小的語法變化原來是非常方便的!您可以在參數列表中的最后一個參數之后放置一個附加的尾隨逗號。然后,您可以交換行或添加新參數,而不必添加或刪除丟失的逗號。
其他主要變化
Kotlin 1.3.40 中引入了的有用的typeof函數將變得穩定并在所有平臺上得到支持。
1.3.60 版本博客文章中已經描述了使您可以在when內啟用break和continue的功能。