Kotlin 1.4.20釋出!

kotliner發表於2020-11-26

Kotlin 1.4.20正帶著新的實驗特性向你走來。Kotlin團隊始終如一地接納社群的反饋,我們需要你對新特性原型的想法。嘗試一下,並在Slack(點選獲取邀請)或YouTrack進行反饋。

Kotlin 1.4.20

下面是部分關鍵點:

  • 支援新的JVM特性,例如透過invokedynamic實現字串拼接。
  • 改善了KMM專案的效能和異常處理。
  • JDK Path類的擴充套件:Path("dir")/"file.txt"

我們還為現有功能(包括1.4.0中新增的特性)提供了許多修復和改進。因此,如果你在使用這些功能時遇到問題,現在是時候再次嘗試了。

繼續閱讀以瞭解有關Kotlin 1.4.20特性的更多資訊。還可以在Kotlin文件Kotlin 1.4.20的新特性頁面上找到該發行版的簡介。完整的變更列表可以在更新日誌中查閱。

與往常一樣,我們要感謝外部貢獻者為該版本提供的幫助。

下面讓我們盡情感受更新的細節吧!

Kotlin/JVM

在JVM上,我們新增了新的目標JVM 15,主要側重於改進現有功能和效能,以及修復錯誤。

透過invokedynamic實現字串拼接

從Java 9開始,JVM上的字串拼接透過動態方法呼叫實現了(位元組碼中的invokedynamic指令)。和以前的實現相比,它的速度更快,記憶體消耗更少,並已為將來的最佳化留出了空間,而無需改動位元組碼。

為了更優異的效能,我們已經著手在Kotlin中實現這個機制,同時在目標JMV9+上,字串的拼接會編譯為動態呼叫。

當前這是個實驗特性,涵蓋以下情況:

  • 運算子(a + b),顯式呼叫(a.plus(b))以及方法引用((a::plus)(b))上的String.plus
  • data class和內聯的toString方法。
  • 字串模板,只有一個非常量引數的除外(參考KT-42457)。

要開啟invokedynamic字串拼接,請將-Xstring-concat配置及以下值之一新增到編譯器選項中:

Kotlin/JS

Kotlin/JS繼續快速發展,該版本帶來了許多改進,包括其專案嚮導的新模板,更好控制專案配置的DSL等。新的IR編譯器還採用了一種全新的方式來編譯專案,這會忽略程式碼中的錯誤。

Gradle DSL的變動

Kotlin/JS Gradle DSL已經獲得了許多更新,這些更新簡化了專案的配置和自定義,包括對Webpack配置的調整,對自動生成的package.json檔案的修改以及對transitive dependencies控制的改進。

單點配置webpack

Kotlin 1.4.20為browser目標引入了一個新的配置塊,名為commonWebpackConfig。在其中,你可以從一個點調整通用設定,而無需複製webpackTaskrunTasktestTask的配置。

要預設啟用所有三個任務的CSS支援,只需要在專案的build.gradle(.kts)中包含以下片段:

從Gradle自定義package.json

package.json檔案通常定義了JavaScript專案的行為,識別可以執行的指令碼,依賴配置等。它是Kotlin/JS專案在構建期間自動生成的。由於package.json的內容因專案而異,因此,我們收到了很多簡化該檔案的編輯的請求。

從Kotlin 1.4.20開始,你可以從Gradle構建指令碼中將條目新增到package.json專案檔案。要將自定義欄位新增到package.json中,請使用compilations的packageJson塊中的customField函式:

當構建專案時,下述塊將被新增到配置檔案中build/js/packages/projectName/package.json:

無論你是要向配置中新增scripts field,要從命令列簡單地執行專案,還是要包含來自其他後處理工具的資訊,我們都希望你能發現這種指定自定義欄位的新方法很有用。

SYarn的選擇性依賴項解析(實驗)

當包含npm中的依賴項時,有時你希望能對依賴項(transitive dependencies)進行細粒度的控制。可能有許多原因。你要對正在使用的庫其中之一的依賴項進行重要升級。或者,你可能想回滾對transitive dependency的更新,這個更新會中斷應用程式的開發。Yarn的選擇性依賴項解析讓你可以覆蓋原作者指定的依賴項,因此可以繼續進行開發。

在Kotlin 1.4.20,我們提供了一種初步的(實驗性)特性,可以從專案的Gradle構建指令碼中配置這個特性。儘管我們仍在針對其餘Kotlin/JS配置進行平滑的API整合,但是你已經可以透過YarnPlugin中的YarnRootExtension使用該特性了。要影響專案已發版的軟體包,請使用resolution函式。在其引數中,指定包名稱選擇器(由Yarn指定)和所需的版本。

build.gradle.kts檔案中選擇性依賴項解析的示例配置如下所示:

在這個例子中,所有npm依賴項需要的react其版本都為16.0.0,而processor將收到其3.0.0版本的deamelize依賴項。此外,還可以將includeexclude呼叫傳遞給resolution塊,這讓你能夠指定版本約束。

禁用精細工作區(實驗)

為了加快構建時間,Kotlin/JS Gradle外掛僅安裝特定Gradle任務所需的依賴項。例如,僅當執行\*Run任務其一時才安裝webpack-dev-server包,而不會在執行assemble任務時去安裝。雖然這意味著避免了不必要的下載,但當並行執行多個Gradle程式時,仍然會有問題。當依賴發生衝突時,重複安裝npm軟體包可能會引發錯誤。

要解決這個問題,Kotlin 1.4.20包含一個新的(實驗性)配置項來禁用這些所謂的精細工作區。像對選擇性依賴項解析的實驗性支援一樣,該特性目前也可以透過YarnRootExtension訪問,但可能會與Kotlin/JS Gradle DSL的其餘部分整合更密切。請將以下片段新增到build.gradle.kts檔案中來使用這個特性:

透過這個配置,Kotlin/JS Gradle外掛將安裝專案會用到的所有npm依賴項,包括當前未執行任務的依賴項。這意味著首次Gradle構建可能會花費一些時間,但是對於執行的所有任務,其下載的依賴項都是最新的。這樣便能避免在並行執行多個Gradle程式時的衝突。

新的嚮導模板

為了能更簡單地建立自定義專案,Kotlin的專案嚮導附帶了針對Kotlin/JS應用程式的可調整新模板。同樣瀏覽器和Node.js執行時環境都有模板。它們是你專案的最佳起點,並可以微調初始配置。包括啟用新的IR編譯器或配置其他支援庫等等的設定。

在Kotlin 1.4.20,有三個可用的模板:

瀏覽器應用程式允許您設定在瀏覽器中執行的準系統Kotlin / JS Gradle專案。 React Application包含使用適當的kotlin包裝器開始構建React應用所需的一切。它提供了用於啟用樣式表,導航元件和狀態容器整合的選項。 Node.js應用程式會預先配置您的專案以在Node.js執行時中執行。它帶有直接包含實驗性kotlinx-nodejs軟體包的選項,我們在上一篇文章中介紹了該軟體包。

  • 瀏覽器應用 允許你建立在瀏覽器中執行的準系統Kotlin/JS Gradle專案。
  • React應用包含透過合適的kotlin包裝器開始構建React App所需要的一切。它提供了用於啟用樣式表,導航元件和狀態容器整合的配置項。
  • Node.js應用會預先配置你的專案以能在Node.js執行時中執行。提供了直接包含實驗性kotlinx-nodejs包的配置項,我們在之前的文章中介紹了這個軟體包。

忽略編譯異常(實驗)

在Kotlin 1.4.20中,我們也很高興地展示Kotlin/JS IR編譯器中可用的全新特性——忽略編譯錯誤。這個特效能在一般情況無法透過編譯的狀態下也可以執行你的應用程式。例如,當你在進行復雜的重構或處理與編譯異常完全無關的系統部分時。使用這種新的編譯器模式,編譯器將忽略任何錯誤程式碼,並用執行時異常對其進行替換,而不是停止編譯。

Kotlin 1.4.20有兩個忽略程式碼中編譯異常的退讓策略:

  • SEMANTIC模式下,編譯器將接受語法上正確但在語義上沒有意義的程式碼。例如,型別不匹配的語句(像是val x: String = 3)。
  • SYNTAX模式下,編譯器接受任何程式碼,幾遍它包含語法錯誤。無論你如何編碼,編譯器仍將嘗試生成能執行的可執行檔案。

作為實驗性特性,忽略編譯錯誤需要透過編譯器配置項選擇性加入。僅適用於Kotlin/JS IR編譯器。請將以下片段新增到build.gradle.kts檔案中以啟用它:

我們希望在編寫Kotlin/JS專案時,帶錯誤的編譯能讓你重視反饋迴圈並提高迭代的速度。我們期待在YouTrack中收到你的反饋,以及嘗試這個特性時發現的任何問題。

隨著該特性實現的逐漸完善,我們還將在未來為Kotlin/JS Gradle DSL及其任務提供更深度的整合。

Kotlin/Native

在1.4.20,效能仍然是Kotlin/Native優先考慮的。這個領域的關鍵特性是逃逸分析機制的新原型,我們計劃在未來的發行版中對其進行完善和改進。當然,還有一些較小的效能改進,例如更快的範圍檢查(in)。

另一方面,Kotlin/Native的開發在1.4.20中得到打磨,且修復了錯誤。我們已經解決了很多舊問題,以及1.4新特性所發現的問題,例如程式碼共享機制。一部分改進解決了在極端情況下Kotlin/Native與Kotlin/JVM之間的行為不一致問題,例如屬性初始化或equalshashCode在函式引用上的工作方式。

最後,我們擴充套件了Objective-C的互操作能力,並提供了將Objective-C異常包裝到Kotlin異常的選項,從而可以在Kotlin程式碼中處理它們。

逃逸分析

逃逸分析是編譯器用於確定物件在棧上分配或”逃逸”到堆上的技術。在棧上進行分配更快,而且後續也不需要進行垃圾收集。

儘管Kotlin/Native已經存在區域性逃逸分析,但我們現在介紹一種新的,更有效的全域性逃逸分析的原型實現。在發行版本獨立的編譯階段中執行這個操作(透過-opt編譯器配置項)。

該原型已經產生了一些令人鼓舞的結果,例如基準測試的平均效能提高了10%。我們正在研究最佳化演算法的方案,讓更多物件能在棧上分配,進一步提升程式的效能。

在我們繼續研究原型的同時,你可以透過嘗試並分享實際專案中的結果為我們提供極大的幫助。

如果要禁用逃逸分析階段,請使用-Xdisable-phases=EscapeAnalysis編譯器配置項。

選擇性Objective-C異常包裝

Objective-C中異常的設計與Kotlin中的完全不同。它們初衷僅限於在發現開發中的錯誤。但從技術上來說,Objective-C庫會在執行時丟擲異常。此前在Kotlin/Native中沒有處理這類異常的方式,因此遇到從庫中丟擲的NSException會導致整個Kotlin/Native程式終止執行。

在1.4.20,我們新增了一個配置項來處理執行時異常,避免程式崩潰。你可以選擇透過Kotlin的ForeignException來封裝NSException,以便在Kotlin程式碼中進行處理。這樣的ForeignException包含對原始NSException的引用,該引用可獲取根本原因的資訊。

要啟用對Objective-C異常的封裝,請在cinterop呼叫中指定-Xforeign-exception-mode objc-wrap配置項,或將foreignExceptionMode=objc-wrap屬性新增到.def檔案。如果是透過CocoaPods進行整合,請在pod{}指令碼構建塊的依賴項中指定配置項,如下所示:

預設行為依舊如此:在Objective-C程式碼丟擲異常時,程式終止執行。

CocoaPods外掛改進

改進任務執行

在該正式版中,我們大大改善了任務的執行流程。例如,如果新增新的CocoaPods依賴,則不會重建現有的依賴關係。新增額外的目標也不會觸發對現有目標依賴關係的重建。

DSL擴充套件

在1.4.20中,我們擴充套件了將CocoaPods以來新增到Kotlin專案中的DSL。

除了本地Pod和CocoaPods倉庫中的Pod,你還可以新增對以下型別庫的依賴:

  • 來自自定義倉庫的第三方庫。
  • 來自Git倉庫的遠端庫。
  • 存檔中的庫(也可以透過任意HTTP地址獲得)。
  • 靜態庫。
  • 具有自定義cinterop配置的庫。

仍然支援之前的DSL語法。

在以下示例中,我們測試幾個DSL的變化:

  • 來自Git倉庫的第三方庫的依賴。你可以透過相應的關鍵字來指定標籤,提交或分支,例如:

還可以結合這些關鍵字來指定Pod的必要版本。

  • 來自自定義倉庫的第三方庫的依賴。 透過specRepos的引數來指定:

你可以在Kotlin with CocoaPods sample找到更多的Kotlin示例。

更新了Xcode的整合

為了更好地使用Xcode,Kotlin需要對Podfile進行一些更改:

  • 如果你的Kotlin Pod有任何Git,HTTP或specRepo pod的依賴關係,也需要在Podfile中指定它們。例如,如果你在CocoaPods倉庫中新增了對AFNetworking的依賴,請也在Podfile中宣告:
  • 當在自定義倉庫新增庫時,你也需要將其地址新增到Podfile的開始處

現在整合的錯誤在IntelliJ IDEA中有更詳細的描述了,因此當Podfile有任何問題,你將瞭解到有關如何修復的資訊。

看看CocoaPods的Kotlin示例withXcproject分支。它包含一個現有Xcode專案kotlin-cocoapods-xcproj整合的示例。

支援Xcode 12的庫

我們增加了對Xcode 12附帶的新庫的支援。請盡情在你的Kotlin程式碼中使用它們!

多平臺庫的釋出結構更新

在Kotlin 1.4.20之前,多平臺庫的釋出會包含指定平臺和後設資料。但是,沒有必要完全依賴後設資料進行釋出,因此從未明確使用這個工件。

從Kotlin 1.4.20開始,不再有單獨的後設資料釋出。後設資料工件已被包含在整個庫的釋出中,當被作為公共源集的依賴新增時,後設資料工件將自動解析為合適平臺特定的工件。

請注意,你不能將沒有分類器的空工件新增到庫的根模組下,以滿足諸如Maven Central之類的倉庫的要求,因為這會與模組中已包含的後設資料工件發生衝突。

1.4.20所釋出庫的相容性

如果你啟用了分層專案架構的支援,並且想使用在Kotlin 1.4.20或更高版本中基於該支援釋出的多平臺庫,則還需要將專案中的Kotlin升級到1.4.20或更高版本。

如果你是庫的作者,並且在Kotlin 1.4.20+中釋出了支援分層專案架構的多平臺庫,請記住,還處於舊版本Kotlin且啟用了分層專案架構支援的使用者將無法使用你的庫。他們需要將Kotlin升級到1.4.20或更高版本。

但是,如果你和你的庫的使用者未啟用分層專案架構的支援,則處於早期版本Kotlin使用者仍然可以使用你的庫。

瞭解有關釋出多平臺庫的更多資訊。

標準庫的變動

java.nio.file.Path的擴充套件

從1.4.20開始,標準庫提供了java.nio.file.Path的實驗擴充套件。

像使用kotlin.io包中的java.io.File擴充套件一樣,現在能以符合Kotlin的語言習慣去使用現代JVM的檔案API了。不再需要呼叫Files的靜態方法,因為它們中的大部分現在都已成為Path型別的擴充套件了。

這些擴充套件位於kotlin.io.path包中。由於Path本身可在JDK 7和更高版本中使用,因此該擴充套件放在kotlin-stdlib-jdk7模組中。為了使用它們,你需要選擇加入實驗註解ExperimentPathApi

我們要特別感謝貢獻者AJ Alt對這些擴充套件所提交的初始PR。

String.replace函式的效能改進

我們一直樂於見到Kotlin社群所提出的改進建議,下面是其中一種情況。在這個發行版中,我們更改了String.replace()的函式實現。

區分大小寫的版本基於indexOf來迴圈替換,而不區分大小寫的版本透過正規表示式進行匹配。

在某些情況下,這項改進可加快函式的執行速度。

棄用Kotlin Android Extensions

自從我們建立Kotlin Android Extensions,它們為Kotlin在Android生態中的迅速普及中發揮了巨大作用。透過這些擴充套件,我們為開發人員提供了方便有效的工具,以減少樣板程式碼:

  • 用於UI互動的Synthetic views(kotlinx.android.synthetics)。
  • Parcelable實現生成器(@Parcelize),用於以Parcel的形式傳遞物件。

起初,我們考慮過向kotlin-android-extensions新增更多元件。但最終沒有實現,我們甚至收到了使用者的請求,希望能外掛獨立出來。

另一方面,Android生態一直在發展,開發者不斷發現能讓工作更輕鬆的新工具。Google提供的原生方案現已彌補了Kotlin Android Extensions填補的部分空白。例如,對於UI互動的簡潔語法,現在有Android Jetpack,它提供了取代findViewById檢視繫結,就像Kotlin synthetics一樣。

考慮到這兩個因素,我們決定淘汰synthetics,以支援檢視繫結,併為Parcelable實現生成器遷移到獨立的外掛。

在1.4.20,我們從kotlin-android-extensions中提取了Parcelable實現生成器,併為其餘部分啟動了棄用週期,該週期目前僅針對synthetics。現在可在警告狀態下繼續使用。但在未來你需要將專案切換到其他解決方案。這是將Android專案從synthetics遷移到檢視繫結的指南

現在,可透過新的kotlin-parcelize plugin外掛來使用Parcelable實現生成器。應用此外掛以代替kotlin-android-extensions@Parcelize註解已移到kotlinx.parcelize包。請注意,不能同時應用kotlin-parcelizekotlin-android-extensions到相同模組中。

如何更新

在將專案更新到最新版本的Kotlin之前,可以在play.kotl.in線上嘗試新的語言和標準庫特性。它將很快更新到1.4.20。

在IntelliJ IDEA和Android Studio,你可以更新Kotlin外掛到1.4.20版本。操作指南

如果要在透過早期Kotlin版本建立的專案上使用,請在專案配置中使用1.4.20 Kotlin版本。 有關更多資訊,請參閱GradleMaven的文件。

你可以在-Github發行頁](https://github.com/JetBrains/kotlin/releases/tag/v1.4.20)下載命令列編譯器。

你可以使用隨版本發行的庫的以下版本:

可以在相應的倉庫中找到kotlin-wrappers庫的不同版本(kotlin-react等)。

這裡檢視有關發行版的更多細節和相容庫列表。

如果你在新版本中遇到任何問題,可以在Slack找到幫助(在這裡獲得邀請)並在我們的YouTrack中報告問題。

其他貢獻者

同樣感謝提交的PR合併到該版本中的所有其他貢獻者:

Jinseong Jeon
Toshiaki Kameyama
Steven Schäfer
Mads Ager
Mark Punzalan
Ivan Gavrilovic
pyos
Jim Sproch
Kristoffer Andersen
Aleksandrina Streltsova
cketti
Konstantin Virolainen
AJ Alt
Henrik Tunedal
Juan Chen
KotlinIsland,
Valeriy Vyrva
Alex Chmyr
Alexey Kudravtsev
Andrey Matveev
Aurimas Liutikas
Dat Trieu
Dereck Bridie
Efeturi Money
Elijah Verdoorn
Enteerman
fee1-dead
Francesco Vasco
Gia Thuan Lam
Guillaume Darmont
Jake Wharton
Julian Kotrba
Kevin Bierhoff
Matthew Gharrity
Matts966
Raluca Sauciuc
Ryan Nett
Sebastian Kaspari
Vladimir Krivosheev
n-p-s
Pavlos-Petros Tournaris
Robert Bares
Yoshinori Isogai
Kris
Derek Bodin
Dominik Wuttke
Sam Wang
Uzi Landsmann
Yuya Urano
Norbert Nogacki
Alexandre Juca

相關文章