Kotlin 1.1 的新特性

Kotlin 1.1 的新特性

目錄

JavaScript

從Kotlin 1.1開始,JavaScript目標平台不再當是實驗性的。所有語言功能都支持,並且有許多新的工具用於與前端開發環境集成。更詳細改動列表,請參見下文 。

協程(實驗性的)

Kotlin 1.1的關鍵新特性是協程,它帶來了futureawaityield以及類似的編程模式的支持。Kotlin的設計中的關鍵特性是協程執行的實現是語言庫的一部分,而不是語言的一部分,所以你不必綁定任何特定的編程範式或併發庫。
協程實際上是一個輕量級的線程,可以掛起並稍後恢復。協程通過掛起函數支持:對這樣的函數的調用可能會掛起協程,並啟動一個新的協程,我們通常使用匿名掛起函數(即掛起lambda表達式)。
我們來看看在外部庫kotlinx.coroutines中實現的asyncawait
這裡,async { …… }啟動一個協程,當我們使用await()時,掛起協程的執行,而執行正在等待的操作,並且在等待的操作完成時恢復(可能在不同的線程上) 。
標準庫通過yieldyieldAll函數使用協程來支持惰性生成序列在這樣的序列中,在取回每個元素之後掛起返回序列元素的代碼塊,並在請求下一個元素時恢復。這裡有一個例子:
Target platform: JVM Running on kotlin v. 1.3.11
運行上面的代碼以查看結果。隨意編輯它並再次運行!
更多信息請參見協程文檔教程
請注意,協程目前還是一個實驗性的特性,這意味著Kotlin團隊不承諾在最終的1.1版本時保持該功能的向後兼容性。

其他語言功能

類型別名

類型別名允許你為現有類型定義備用名稱。這對於泛型類型(如集合)以及函數類型最有用。這裡有幾個例子:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其KEEP

已綁定的可調用引用

現在可以使用::操作符來獲取指向特定對象實例的方法或屬性的成員引用以前這只能用lambda表達式表示。這裡有一個例子:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其KEEP

密封類和數據類

Kotlin 1.1 刪除了一些對Kotlin 1.0 中已存在的密封類和數據類的限制。現在你可以在同一個文件中的任何地方定義一個密封類的子類,而不只是以作為密封類嵌套類的方式。數據類現在可以擴展其他類。這可以用來友好且清晰地定義一個表達式類的層次結構:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其文檔或者密封類數據類的KEEP。

lambda 表達式中的解構

現在可以使用解構聲明語法來解開傳遞給lambda表達式的參數。這裡有一個例子:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其文檔及其KEEP

下劃線用於未使用的參數

對於具有多個參數的lambda表達式,可以使用_字符替換不使用的參數的名稱:
Target platform: JVM Running on kotlin v. 1.3.11
這也適用於解構聲明
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其KEEP

數字字面值中的下劃線

正如在Java 8 中一樣,Kotlin 現在允許在數字字面值中使用下劃線來分隔數字分組:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其KEEP

對於屬性的更短語法

對於沒有自定義訪問器、或者將getter 定義為表達式主體的屬性,現在可以省略屬性的類型:
Target platform: JVM Running on kotlin v. 1.3.11

內聯屬性訪問器

如果屬性沒有幕後字段,現在可以使用inline修飾符來標記該屬性訪問器。這些訪問器的編譯方式與內聯函數相同。
Target platform: JVM Running on kotlin v. 1.3.11
你也可以將整個屬性標記為inline——這樣修飾符應用於兩個訪問器。
更詳細信息請參閱其文檔及其KEEP

局部委託屬性

現在可以對局部變量使用委託屬性語法。一個可能的用途是定義一個延遲求值的局部變量:
Target platform: JVM Running on kotlin v. 1.3.11
更詳細信息請參閱其KEEP

委託屬性綁定的攔截

對於委託屬性,現在可以使用provideDelegate操作符攔截委託到屬性之間的綁定。例如,如果我們想要在綁定之前檢查屬性名稱,我們可以這樣寫:
provideDelegate方法在創建MyUI實例期間將會為每個屬性調用,並且可以立即執行必要的驗證。
更詳細信息請參閱其文檔

泛型枚舉值訪問

現在可以用泛型的方式來對枚舉類的值進行枚舉:
Target platform: JVM Running on kotlin v. 1.3.11

對於DSL 中隱式接收者的作用域控制

@DslMarker註解允許限制來自DSL上下文中的外部作用域的接收者的使用。考慮那個典型的HTML構建器示例
在Kotlin 1.0中,傳遞給td的lambda表達式中的代碼可以訪問三個隱式接收者:傳遞給tabletr 和td的。這允許你調用在上下文中沒有意義的方法——例如在td裡面調用tr,從而中放置一個 標籤。
在Kotlin 1.1中,你可以限制這種情況,以使只有在td的隱式接收者上定義的方法會在傳給td的lambda表達式中可用。你可以通過定義標記有@DslMarker元註解的註解並將其應用於標記類的基類。
更詳細信息請參閱其文檔及其KEEP

rem 操作符

mod操作符現已棄用,而使用rem取代。動機參見這個問題

標準庫

字符串到數字的轉換

在String類中有一些新的擴展,用來將它轉換為數字,而不會在無效數字上拋出異常:String.toIntOrNull(): Int?String.toDoubleOrNull(): Double?等。
還有整數轉換函數,如Int.toString()String.toInt()String.toIntOrNull(),每個都有一個帶有radix參數的重載,它允許指定轉換的基數(2到36)。

onEach()

onEach是一個小、但對於集合和序列很有用的擴展函數,它允許對操作鏈中的集合/序列的每個元素執行一些操作,可能帶有副作用。對於迭代其行為像forEach但是也進一步返回可迭代實例。對於序列它返回一個包裝序列,它在元素迭代時延遲應用給定的動作。

also()、takeIf() 和takeUnless()

這些是適用於任何接收者的三個通用擴展函數。
also就像apply:它接受接收者、做一些動作、並返回該接收者。二者區別是在apply內部的代碼塊中接收者是this,而在also內部的代碼塊中是it(並且如果你想的話,你可以給它另一個名字)。當你不想掩蓋來自外部作用域的this時這很方便:
Target platform: JVM Running on kotlin v. 1.3.11
takeIf就像單個值的filter它檢查接收者是否滿足該謂詞,並在滿足時返回該接收者否則不滿足時返回null結合elvis-操作符和及早返回,它允許編寫如下結構:
Target platform: JVM Running on kotlin v. 1.3.11
takeUnlesstakeIf相同,只是它採用了反向謂詞。當它滿足謂詞時返回接收者,否則返回null因此,上面的示例之一可以用takeUnless重寫如下:
當你有一個可調用的引用而不是lambda 時,使用也很方便:
Target platform: JVM Running on kotlin v. 1.3.11

groupingBy()

此API可以用於按照鍵對集合進行分組,並同時折疊每個組。例如,它可以用於計算文本中字符的頻率:
Target platform: JVM Running on kotlin v. 1.3.11

Map.toMap() 和Map.toMutableMap()

這倆函數可以用來簡易複製映射:

Map.minus(key)

運算符plus提供了一種將鍵值對添加到只讀映射中以生成新映射的方法,但是沒有一種簡單的方法來做相反的操作:從映射中刪除一個鍵採用不那麼直接的方式如Map.filter()Map.filterKeys()現在運算符minus填補了這個空白。有4個可用的重載:用於刪除單個鍵、鍵的集合、鍵的序列和鍵的數組。
Target platform: JVM Running on kotlin v. 1.3.11

minOf() 和maxOf()

這些函數可用於查找兩個或三個給定值中的最小和最大值,其中值是原生數字或Comparable對象。每個函數還有一個重載,它接受一個額外的Comparator實例,如果你想比較自身不可比的對象的話。
Target platform: JVM Running on kotlin v. 1.3.11

類似數組的列表實例化函數

類似於Array構造函數,現在有創建ListMutableList實例的函數,並通過調用lambda表達式來初始化每個元素:
Target platform: JVM Running on kotlin v. 1.3.11

Map.getValue()

Map上的這個擴展函數返回一個與給定鍵相對應的現有值,或者拋出一個異常,提示找不到該鍵。如果該映射是用withDefault生成的,這個函數將返回默認值,而不是拋異常。
Target platform: JVM Running on kotlin v. 1.3.11

抽象集合

這些抽像類可以在實現Kotlin集合類時用作基類。對於實現只讀集合,有AbstractCollectionAbstractListAbstractSetAbstractMap,而對於可變集合,有AbstractMutableCollectionAbstractMutableListAbstractMutableSetAbstractMutableMap在JVM上,這些抽象可變集合從JDK的抽象集合繼承了大部分的功能。

數組處理函數

標準庫現在提供了一組用於逐個元素操作數組的函數:比較(contentEqualscontentDeepEquals),哈希碼計算(contentHashCodecontentDeepHashCode),以及轉換成一個字符串(contentToStringcontentDeepToString)。它們都支持JVM (它們作為java.util.Arrays中的相應函數的別名)和JS(在Kotlin標準庫中提供實現)。
Target platform: JVM Running on kotlin v. 1.3.11

JVM 後端

Java 8 字節碼支持

Kotlin現在可以選擇生成Java 8字節碼(命令行選項-jvm-target 1.8或者Ant/Maven/Gradle中的相應選項)。目前這並不改變字節碼的語義(特別是,接口和lambda表達式中的默認方法的生成與Kotlin 1.0中完全一樣),但我們計劃在以後進一步使用它。

Java 8 標準庫支持

現在有支持在Java 7和8中新添加的JDK API的標準庫的獨立版本。如果你需要訪問新的API,請使用kotlin-stdlib-jre7kotlin-stdlib-jre8maven構件,而不是標準的kotlin-stdlib這些構件是在kotlin-stdlib之上的微小擴展,它們將它作為傳遞依賴項帶到項目中。

字節碼中的參數名

Kotlin現在支持在字節碼中存儲參數名。這可以使用命令行選項-java-parameters啟用。

常量內聯

編譯器現在將const val屬性的值內聯到使用它們的位置。

可變閉包變量

用於在lambda表達式中捕獲可變閉包變量的裝箱類不再具有volatile字段。此更改提高了性能,但在一些罕見的使用情況下可能導致新的競爭條件。如果受此影響,你需要提供自己的同步機制來訪問變量。

javax.scripting 支持

Kotlin現在與javax.script API(JSR-223)集成。其API允許在運行時求值代碼段:
關於使用API的示例項目參見這裡 。

kotlin.reflect.full

為Java 9支持準備,在kotlin-reflect.jar庫中的擴展函數和屬性已移動kotlin.reflect.full包中。舊包(kotlin.reflect)中的名稱已棄用,將在Kotlin 1.2中刪除。請注意,核心反射接口(如KClass)是Kotlin標準庫(而不是kotlin-reflect)的一部分,不受移動影響。

JavaScript 後端

統一的標準庫

Kotlin標準庫的大部分目前可以從代碼編譯成JavaScript來使用。特別是,關鍵類如集合(ArrayListHashMap等)、異常(IllegalArgumentException等)以及其他幾個關鍵類(StringBuilderComparator)現在都定義在kotlin包下。在JVM平台上,一些名稱是相應JDK類的類型別名,而在JS平台上,這些類在Kotlin標準庫中實現。

更好的代碼生成

JavaScript 後端現在生成更加可靜態檢查的代碼,這對JS 代碼處理工具(如minifiers、 optimisers、 linters 等)更加友好。

external 修飾符

如果你需要以類型安全的方式在Kotlin中訪問JavaScript實現的類,你可以使用external修飾符寫一個Kotlin聲明。(在Kotlin 1.0中,使用了@native註解。)與JVM目標平台不同,JS平台允許對類和屬性使用external修飾符。例如,可以按以下方式聲明DOM Node類:

改進的導入處理

現在可以更精確地描述應該從JavaScript模塊導入的聲明。如果在外部聲明上添加@JsModule("<模块名>")註解,它會在編譯期間正確導入到模塊系統(CommonJS或AMD)。例如,使用CommonJS,該聲明會通過require(……)函數導入。此外,如果要將聲明作為模塊或全局JavaScript對象導入,可以使用@JsNonModule註解。
例如,以下是將JQuery 導入Kotlin 模塊的方法:
在這種情況下,JQuery將作為名為jquery的模塊導入。或者,它可以用作$-對象,這取決於Kotlin編譯器配置使用哪個模塊系統。
你可以在應用程序中使用如下所示的這些聲明:
參考資料,google 繁體中文機器翻譯:https://kotlinlang.org/docs/reference/whatsnew11.html

留言

這個網誌中的熱門文章

16天記下7000單字