Kotlin 1.3.50正式版釋出

kotliner發表於2019-10-05

今天我們很高興地迎來Kotlin 1.3.50版本的正式釋出。除了一如以往的質量和工具的優化,該新版重點如下:

  • 提供了新的持續時間和測量時間API(僅供預覽)
  • 改進了Java-to-Kotlin轉換器
  • 嘗試在Gradle Kotlin/JS專案中(使用Dukat)生成npm依賴項的外部宣告
  • 用於在IntelliJ IDEA Ultimate中除錯Kotlin/Native程式碼的獨立外掛
  • 多平臺專案中支援Java編譯

你可以在更新日誌中查閱完整的列表。如往常一樣,我們非常感謝外部的貢獻者。下面一起來領略詳盡的更新內容吧。

Kotlin 1.4針對空檢查的優化

如你所知,Kotlin通過可空型別來避免發生NullPointerException異常。 但是與Java程式碼的互操作性導致無法完全避免NPE。 為了在NPE崩潰發生時,讓開發人員更容易地查詢到問題的根源,Kotlin編譯器不止丟擲NPE,還會丟擲帶有清晰錯誤訊息的各種型別的執行時異常。 事實證明,這種方法有其缺點:它減少了可能由Kotlin編譯器或各種位元組碼處理工具(例如Android R8優化器)執行的空檢查優化。

為了解決這個問題,從Kotlin 1.4開始,所有執行時null檢查都會丟擲java.lang.NullPointerException而不是KotlinNullPointerExceptionIllegalStateExceptionIllegalArgumentExceptionTypeCastException。 這適用於!!操作符,method preamble中的引數null檢查,平臺型別的表示式null檢查以及具有非null型別的as運算子。 這不適用於lateinit空檢查和諸如checkNotNullrequireNotNull之類的顯式庫函式呼叫。

但是這不會對開發者有太大改變:Kotlin程式碼丟擲的異常,其所攜帶的異常資訊仍和以前一樣。 異常的型別發生了變化,但是傳遞的資訊保持不變。 例如,以下程式碼現在會丟擲一個IllegalStateException,其錯誤訊息為”JavaCode.getNull()不得為空”:

在第1行中的duplicate函式呼叫之前,將生成一個特殊檢查,如果表示式JavaCode.getNull()儲存null,則會丟擲此異常。從Kotlin 1.4開始,此程式碼將丟擲NullPointerException代替異常資訊”JavaCode.getNull()不得為null”。

在這個變動後,優化器通過刪除冗餘空檢查來儘可能地減少位元組碼中空檢查的總數:由於所有檢查都丟擲相同的NPE異常,因此可以只保留一個NPE異常。在此種優化過程中,NPE中的一些有用資訊可能會丟失,這就是獲得更好效能所要付出的代價。請注意,這些優化方案只會在對應的工具中實現,並且在實現時會有更多詳細資訊,但是異常型別的變動可能會在未來版本實裝。

標準庫的變化

請留意所有新功能都以“實驗”狀態新增到標準庫中。

持續時間和測量時間API

新的持續時間和時間測量API已提供預覽版本。可通過秒,毫秒,納秒等等多種單位度量持續時間。已知不同單位之間混用會導致bug:如果要求API將持續時間儲存為像“ Long”這樣的原始型別,則可能會使用錯誤的單位傳遞值,不幸的是型別系統無法協助避免這種情況。儘管建立一個常規類來儲存持續時間可以解決這個問題,但又帶來了另一個問題:額外的消耗。

內聯類提供了一個非常優雅的解決方案:它既保證了型別,也不會產生消耗。現在,API可以使用Duration型別,並且所有客戶端都需要顯式指定單位。由於Duration被宣告為一個內聯類,因此不需要額外的消耗:

這個版本支援單調時鐘”MonoClock”。推薦使用單調時鐘來從程式中給定點開始測量耗時,該時鐘不依賴於系統時間。因為外部可能會改變系統時間,所以可能會導致偏差。單調時鐘只能測量給定點之間的時間,而無法知道“當前時間”。

這個Clock介面提供了一個常規的API去測量時間間隔。MonoClock是實現了Clock的物件;它提供了不同平臺上預設的單調時間源。

使用“Clock”介面時,你需要明確動作開始的時間,以及開始後經過的時間。這能滿足你在不同方法裡呼叫開始和結束。

measureTimedValue函式可以測試某個操作的耗時,同時結果和耗時都會通過返回值獲得。函式內部是通過MonoClock測量方法的耗時。

想了解更多關於Duration類的實現,以及對於不同平臺Clock介面和MonoClock實現的詳細資訊,請查閱 KEEP。請注意這個API目前仍處於試驗狀態,可能會根據你的反饋而有相應的更改。你需要明確標示註釋來使用這些API。

我們非常歡迎你的反饋!

位操作函式

現在標準庫包含用於位操作的API(當然,還在測試階段):

注意已對Int、Long、Short、Byte及其對應的無符號型別新增了類似的擴充套件函式。

IntelliJ IDEA支援

Java to Kotlin轉換器的優化

我們正計劃改進Java-to-Kotlin的轉換器,以最大程度減少轉換後必須手動修復的”異常程式碼”數量。由於現在的轉換器基本都生成為不可空的型別,而使得你需要手動去修改這些可空性問題。這通常都會在執行時由於是否為空的匹配異常而報錯。

經過優化的Java-to-Kotlin轉換器新版本,將會嘗試根據程式碼中的Java型別用法,而儘可能去推斷可空性。不可能生成100%無錯誤的程式碼。旨在減少編譯錯誤的數量,並使生成的Kotlin程式碼更易於修改。新的轉換器也修復了許多已知的錯誤。例如,現在能正確處理隱式Java型別轉換了。

新的轉換器將在未來成為預設選擇。在當前版本中,僅供試用。要開啟它,在設定中勾選Use New J2K(experimental)

請儘可能地試用並給予我們反饋!

除錯模式的改善

我們改善了Kotlin“變數”的呈現方式。由於位元組碼中還有很多額外的開發資訊,因此Kotlin“變數”介面僅會突顯相關變數。若你該版本在lambda(內聯或非內聯)中設定斷點,它將比之前表現得更好。 lambda內部的區域性變數以及從外部上下文和外部函式的引數捕獲的變數都能清晰顯示出來:

debug_lambda_variables

現在你可以根據需要在函式的末尾設定斷點了:

end_of_function_breakpoint

對於許多”特殊”的語言特性(例如本地擴充套件函式或成員擴充套件屬性的訪問器),已實現了除錯中“Evaluate expression”功能的支援。同樣現在你可以通過“Evaluate expression”修改變數了:

img

當然你也可以直接在“變數”介面中修改變數。

新的intentions和inspections

新增了新的intentions和inspections。 其目的是幫助你習慣Kotlin程式碼的編寫方式。 例如,以下intention建議用indices屬性代替建立索引範圍:

img

如果不使用索引,則可以通過for迴圈自動遍歷元素。

IntelliJ IDEA現狀:

  • 可以通過Delegates.notNull()語法自動替換基本型別的lateinit屬性。
  • 支援將普通屬性轉換為懶載入屬性返回
  • 檢測Java用於陣列比較的方法(例如Arrays.equals()Array.deepEquals()),並建議將其替換為與Kotlin對應的方法(例如contentEqualscontentDeepEquals)。
  • 在comletion列表中高亮被標記deprecated的引用。
deprecated_imports

IDE基本操作的效能已經得到優化了,修復了已知會導致UI凍結的幾種情況(例如在程式碼繁複的檔案上使用”Move”進行重構)。

Kotlin/JS

這次更新支援在Windows上使用org.jetbrains.kotlin.js外掛構建和執行Kotlin / JS Gradle專案。你可以像其他平臺一樣使用Gradle任務來構建和執行專案,解決幷包含Gradle配置中所需的NPM依賴關係,也可以通過webpack-dev-server試執行應用程式(例如通過呼叫Gradle中的browserRun任務), 還有更多的功能。和其他平臺一樣,以上無需安裝和配置node、npm和yarn的分發就可直接使用。

在看不到的地方,Kotlin/JS還進行了一系列效能改進,縮短了專案的增量編譯時間。這意味著最優情況下能比1.3.41快30%。

我們改善對NPM的整合意味著專案現在支援並行和懶載入,並且增加了對同一專案編譯之間具有依賴傳遞的專案的支援。

新版本中所生成元件結構和命名也有所變化。 現在,生成的元件被捆綁在發行資料夾中,其中包括專案的版本號和archiveBaseName(預設為專案名稱),例如 projectName-1.0-SNAPSHOT.js

Dukat

Dukat 允許將TypeScript宣告檔案(.d.ts)自動轉換為Kotlin外部宣告(代替了ts2kt命令列工具)。 這極大減少了手動編寫JS庫包裝器的需求,這方便於Kotlin以型別安全的方式呼叫JavaScript生態中的庫。

Kotlin/JS現在為Gradle專案的dukat整合提供了實驗性支援。執行整合在Gradle的構建任務,可以自動為npm依賴項生成Typesafe包裝器,並能直接在Kotlin中使用。

kotlin-dukat-preview

由於dukat還處於早起階段,因此預設禁用其整合。在專案根目錄的gradle.properties檔案中增加kotlin.js.experimental.generateKotlinExternals=true配置行,可啟用dukat。我們也提供了一個示例專案 ,演示如何在Kotlin/JS專案中使用dukat,請使用並給予我們你的反饋

Kotlin/Native

對於分辨Kotlin/Native與Kotlin的版本並非一件易事。但這個噩夢已然終結, Kotlin和Kotlin/Native的版本現已統一。Kotlin和Kotlin/Native都統一使用1.3.50來命名該發行版本,從而減少了的混亂。

該版本為所有平臺(包括macOS和iOS)帶來了更多預載入的Apple框架。 Kotlin/Native編譯器現會在生成的框架中包含實際的中間碼。

互操作性得到了改善。 現在,框架生成支援kotlin.Deprecated註釋,並且生成的Objective-C headers code將不會有警告。 getOriginalKotlinClass()函式已新增到標準庫,允許從Objective-C類或協議中獲取KClass

標準庫已更新並支援Kotlin/Native型別的kotlin.reflect.typeOf()函式。 Worker型別增加了新函式executeAfter(),可在指定延遲後執行操作。 另外,您可以在Worker上呼叫processQueue()函式來顯式處理任務佇列。

舊函式ByteArray.stringFromUtf8()ByteArray.stringFromUtf8OrThrow()已不推薦使用了。 在之前的版本中,我們新增了ByteArray.decodeToString()函式(在kotlin.text包),以將UTF-8字串轉換為Kotlin字串。 該函式不支援以NULL終止的字串,因此,為了解決該問題,在1.3.50中,我們新增了一個新的函式來處理以NULL終止的UTF-8字串。ByteArray.toKString()函式(位於kotlinx.cinterop包)可用於將以NULL結尾的UTF-8字串轉換為Kotlin字串。 你可以根據需求傳遞起始索引和結束索引作為引數。

我們已棄用並刪除了kotlin-platform-nativeGradle外掛,轉而推薦使用kotlin-multiplatformGradle外掛,這非常利於你的多平臺專案。 查閱文件以獲得遷移指南和更多的資訊

最後,我們非常高興能分享該版本中Kotlin/Native編譯器和interop工具效能的改善狀況。

多平臺專案

現在,可以通過呼叫DSL新增的withJava()函式,將Java編譯包含到多平臺專案的Kotlin/JVM目標中。 它將預設配置Java外掛並使用src / <targetName> Main / java和src / <targetName> Test / java路徑。 下面是一個完整的示例,通過啟用Java編譯來建立Kotlin/JVM目標:

Kotlin的|新建專案嚮導現可以為新專案生成Gradle Kotlin DSL。

現在也支援在IntelliJ IDEA Ultimate中除錯Kotlin/Native程式碼了! 嘗試安裝新的IntelliJ IDEA Ultimate的Native除錯外掛。 它會檢測Kotlin/Native執行配置,並支援除錯操作:

debugging-kotlin-native-1.3.50

指令碼

該版本為指令碼和REPL改善了效能並新增了多項特性。 使用Kotlin作為應用程式的指令碼語言更加容易! 現在指令碼支援開箱即用:我們已經發布了一個預設的JSR-223實現庫,因此若要為你的應用程式新增Kotlin指令碼支援,只需新增kotlin-scripting-jsr223依賴項並使用 Kotlin的javax.script API。

現在JSR-223 API設定的屬性在指令碼中可作為常規Kotlin屬性進行訪問了(在這之前必須使用bindings對映):

在Kotlin1.3版本中為了簡化建立和編寫基礎通用指令碼而引入的kotlin-main-kts元件,現在也可以作為JSR-223的標頭檔案。 除去解決依賴關係的諸如RepositoryDependsOn之類的註釋外,現在還支援“ @Import”註釋,指示指令碼編譯器將另一個指令碼“匯入”到當前指令碼中:

閱讀KEEP-75.以瞭解更多有關指令碼的資訊。你可以在Kotlin倉庫裡獲取示例。請在Kotlin Slack的#scripting頻道中分享你的反饋!

如何升級

你仍然可以在play.kotl.in線上Kotlin

  • Maven, Gradle, and npm:修改編譯器和標準庫的版本為1.3.50 。可以在這裡檢視文件。
  • IntelliJ IDEAAndroid Studio:升級Kotlin外掛到1.3.50。開啟Tools | Kotlin | Configure Kotlin Plugin Updates點選“Check for updates now”按鈕。
  • Eclipse:通過Marketplace安裝外掛。
  • Github release頁面下載命令列編譯版本。

如果你在新版本中遇到任何問題,歡迎在Slack的論壇上尋求幫助(在這裡),或在問題跟蹤器中報告問題。

請盡情享受Kotlin!

外部的貢獻者

我們要特別感謝Toshiaki Kameyama正在進行的工作,為IntelliJ IDEA提供許多有用的意圖和檢查。

我們要感謝所有外部貢獻者,他們的PR都包含在這個版本中:

相關文章