Kotlin 1.2 的新特性
Kotlin 1.2 的新特性
目錄
多平台項目(實驗性的)
多平台項目是Kotlin 1.2中的一個新的實驗性的特性,允許你在支持Kotlin的目標平台——JVM、JavaScript以及(將來的)Native之間重用代碼。在多平台項目中,你有三種模塊:
- 一個公共模塊包含平台無關代碼,以及無實現的依賴平台的API聲明。
- 平台模塊包含通用模塊中的平台相關聲明在指定平台的實現,以及其他平台相關代碼。
- 常規模塊針對指定的平台,既可以是平台模塊的依賴,也可以依賴平台模塊。
當你為指定平台編譯多平台項目時,既會生成公共代碼也會生成平台相關代碼。
多平台項目支持的一個主要特點是可以通過預期聲明與實際聲明來表達公共代碼對平台相關部分的依賴關係。一個預期聲明指定一個API(類、接口、註解、頂層聲明等)。一個實際聲明要么是該API的平台相關實現,要么是一個引用到在一個外部庫中該API的一個既有實現的別名。這是一個示例:
在公共代碼中:
在JVM 平台代碼中:
其他語言特性
註解中的數組字面值
自Kotlin 1.2起,註解的數組參數可以通過新的數組字面值語法傳入,而無需使用
arrayOf
函數:
該數組字面值語法僅限於註解參數。
lateinit 頂層屬性與局部變量
lateinit
修飾符現在可以用於頂層屬性與局部變量了。例如,後者可用於當一個lambda表達式作為構造函數參數傳給一個對象時,引用另一個必須稍後定義的對象:
Target platform: JVM Running on kotlin v. 1.3.11
檢查lateinit 變量是否已初始化
現在可以通過屬性引用的
isInitialized
來檢測該lateinit var是否已初始化:
Target platform: JVM Running on kotlin v. 1.3.11
內聯函數帶有默認函數式參數
內聯函數現在允許其內聯函式數參數具有默認值:
Target platform: JVM Running on kotlin v. 1.3.11
源自顯式類型轉換的信息會用於類型推斷
Kotlin編譯器現在可將類型轉換信息用於類型推斷。如果你調用一個返回類型參數
T
的泛型方法並將返回值轉換為指定類型Foo
,那麼編譯器現在知道對於本次調用需要綁定類型為Foo
。
這對於Android開發者來說尤為重要,因為編譯器現在可以正確分析Android API級別26中的泛型
findViewById
調用:智能類型轉換改進
當一個變量有安全調用表達式與空檢測賦值時,其智能轉換現在也可以應用於安全調用接收者:
Target platform: JVM Running on kotlin v. 1.3.11
智能轉換現在也允許用於在lambda 表達式中局部變量,只要這些局部變量僅在lambda 表達式之前修改即可:
Target platform: JVM Running on kotlin v. 1.3.11
支持::foo 作為this::foo 的簡寫
現在寫綁定到
this
成員的可調用引用可以無需顯式接收者,即::foo
取代 this::foo
。這也使在引用外部接收者的成員的lambda表達式中使用可調用引用更加方便。阻斷性變更:try 塊後可靠智能轉換
Kotlin以前將
try
塊中的賦值語句用於塊後的智能轉換,這可能會破壞類型安全與空安全並引發運行時故障。這個版本修復了該問題,使智能轉換更加嚴格,但可能會破壞一些依靠這種智能轉換的代碼。
如果要切換到舊版智能轉換行為,請傳入回退標誌
-Xlegacy-smart-cast-after-try
作為編譯器參數。該參數會在Kotlin 1.3中棄用。棄用:數據類棄用copy
當從已具有簽名相同的
copy
函數的類型派生數據類時,為數據類生成的copy
實現使用超類型的默認值,這導致反直覺行為,或者導致運行時失敗,如果超類型中沒有默認參數的話。
導致
copy
衝突的繼承在Kotlin 1.2中已棄用並帶有警告,而在Kotlin 1.3中將會是錯誤。棄用:枚舉條目中的嵌套類型
由於初始化邏輯的問題,已棄用在枚舉條目內部定義一個非
inner class
的嵌套類。這在Kotlin 1.2中會引起警告,而在Kotlin 1.3中會成為錯誤。棄用:vararg 單個命名參數
為了與註解中的數組字面值保持一致,向一個命名參數形式的vararg參數傳入單個項目的用法(
foo(items = i)
)已被棄用。請使用伸展操作符連同相應的數組工廠函數:
在這種情況下有一項防止性能下降的優化可以消除冗餘的數組創建。單參數形式在Kotlin 1.2 中會產生警告,而在Kotlin 1.3中會放棄。
棄用:擴展Throwable 的泛型類的內部類
繼承自
Throwable
的泛型類的內部類可能會在throw-catch場景中違反類型安全性,因此已棄用,在Kotlin 1.2中會是警告,而在Kotlin 1.3中會是錯誤。棄用:修改只讀屬性的幕後字段
通過在自定義getter中賦值
field = ……
來修改只讀屬性的幕後字段的用法已被棄用,在Kotlin 1.2中會是警告,而在Kotlin 1.3中會是錯誤。標準庫
Kotlin 標準庫構件與拆分包
Kotlin標準庫現在完全兼容Java 9的模塊系統,它禁止拆分包(多個jar文件聲明的類在同一包中)。為了支持這點,我們引入了新的
kotlin-stdlib-jdk7
與kotlin-stdlib-jdk8
,它們取代了舊版的kotlin-stdlib-jre7
與kotlin-stdlib-jre8
。
在Kotlin看來新的構件中的聲明在相同的包名內,而在Java看來有不同的包名。因此,切換到新的構件無需修改任何源代碼。
確保與新的模塊系統兼容的另一處變更是在
kotlin-reflect
庫中刪除了 kotlin.reflect
包中棄用的聲明。如果你正在使用它們,你需要切換到使用kotlin.reflect.full
包中的聲明,自Kotlin 1.1起就支持這個包了。windowed、chunked、zipWithNext
用於
Iterable
、Sequence
與CharSequence
的新的擴展覆蓋了這些應用場景:緩存或批處理(chunked
)、滑動窗口與計算滑動均值(windowed
)以及處理成對的後續條目(zipWithNext
):
Target platform: JVM Running on kotlin v. 1.3.11
fill、replaceAll、shuffle/shuffled
添加了一些用於操作列表的擴展函數:
MutableList
的fill
、replaceAll
與shuffle
,以及只讀List
的shuffled
:
Target platform: JVM Running on kotlin v. 1.3.11
kotlin-stdlib 中的數學運算
為滿足由來已久的需求,Kotlin 1.2添加了JVM與JS公用的用於數學運算的
kotlin.math
API,包含以下內容:- 常量:
PI
與E
; - 三角函數:
cos
、sin
、tan
及其反函數:acos
、asin
、atan
、atan2
; - 雙曲函數:
cosh
、sinh
、tanh
及其反函數:acosh
、asinh
、atanh
- 指數函數:
pow
(擴展函數)、sqrt
、hypot
、exp
、expm1
; - 對數函數:
log
、log2
、log10
、ln
、ln1p
; - 取整:
ceil
、floor
、truncate
、round
(奇進偶舍)函數;roundToInt
、roundToLong
(四捨五入)擴展函數;
- 符號與絕對值:
abs
與sign
函數;absoluteValue
與sign
擴展屬性;withSign
擴展函數;
- 兩個數的最值函數:
max
與min
; - 二進製表示:
ulp
擴展屬性;nextUp
、nextDown
、nextTowards
擴展函數;toBits
、toRawBits
、Double.fromBits
(這些在kotlin
包中)。
這些函數同樣也有
Float
參數版本(但不包括常量)。用於BigInteger 與BigDecimal 的操作符與轉換
Kotlin 1.2引入了一些使用
BigInteger
與BigDecimal
運算以及由其他數字類型創建它們的函數。具體如下:toBigInteger
用於Int
與Long
;toBigDecimal
用於Int
、Long
、Float
、Double
以及BigInteger
;- 算術與位運算操作符函數:
- 二元操作符
+
、-
、*
、/
、%
以及中綴函數and
、or
、xor
、shl
、shr
; - 一元操作符
-
、++
、--
以及函數inv
。
- 二元操作符
浮點數到比特的轉換
添加了用於將
Double
及Float
與其比特表示形式相互轉換的函數:toBits
與toRawBits
對於Double
返回Long
而對於Float
返回Int
;Double.fromBits
與Float.fromBits
用於有相應比特表示形式創建浮點數。
正則表達式現在可序列化
kotlin.text.Regex
類現在已經是Serializable
的了並且可用在可序列化的繼承結構中。如果可用,Closeable.use 會調用Throwable.addSuppressed
當在其他異常之後關閉資源期間拋出一個異常,
Closeable.use
函數會調用Throwable.addSuppressed
。
要啟用這個行為,需要依賴項中有
kotlin-stdlib-jdk7
。JVM 後端
構造函數調用規範化
自1.0版起,Kotlin就已支持帶有復雜控制流的表達式,諸如try-catch表達式以及內聯函數。根據Java虛擬機規範這樣的代碼是有效的。不幸的是,當這樣的表達式出現在構造函數調用的參數中時,一些字節碼處理工具不能很好地處理這種代碼。
為了緩解這種字節碼處理工具用戶的這一問題,我們添加了一個命令行選項(
-Xnormalize-constructor-calls=模式
),告訴編譯器為這樣的構造過程生成更接近Java的字節碼。其中模式
是下列之一:disable
(默認)——以與Kotlin 1.0 即1.1 相同的方式生成字節碼;enable
——為構造函數調用生成類似Java 的字節碼。這可能會改變類加載與初始化的順序;preserve-class-initialization
——為構造函數調用生成類似Java的字節碼,並確保類初始化順序得到保留。這可能會影響應用程序的整體性能;僅用在多個類之間共享一些複雜狀態並在類初始化時更新的場景中。
“人工”解決辦法是將具有控制流的子表達式的值存儲在變量中,而不是直接在調用參數內對其求值。這與
-Xnormalize-constructor-calls=enable
類似。Java 默認方法調用
在Kotlin 1.2之前,針對JVM 1.6的接口成員覆蓋Java默認方法會產生一個關於超類型調用的警告:
Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'
(“針對JVM 1.6的Java默認方法的超類型調用已棄用,請使用'-jvm-target 1.8 '重新編譯”)。在Kotlin 1.2中,這是一個**錯誤**,因此這樣的代碼都需要針對JVM 1.8編譯。阻斷性變更:平台類型x.equals(null) 的一致行為
在映射到Java原生類型(
Int!
、Boolean!
、Short!
、Long!
、Float!
、Double!
、Char!
)的平台類型上調用x.equals(null)
,當x
為null
時錯誤地返回了true
。自Kotlin 1.2起,在平台類型的空值上調用x.equals(……)
都會拋出NPE (但x == ...
不會)。
要返回到1.2之前的行為,請將標誌
-Xno-exception-on-explicit-equals-for-boxed-null
傳給編譯器。阻斷性變更:修正平台null 透過內聯擴展接收者逃逸
在平台類型的空值上調用內聯擴展函數並沒有檢測接收者是否為null, 因而允許null 逃逸到其他代碼中。Kotlin 1.2 在調用處強制執行這項檢測, 如果接收者為空就拋出異常。
要切換到舊版行為,請將回退標誌
-Xno-receiver-assertions
傳給編譯器。JavaScript 後端
默認啟用TypedArrays 支持
工具
警告作為錯誤
編譯器現在提供一個將所有警告視為錯誤的選項。可在命令行中使用
-Werror
,或者在Gradle中使用以下代碼片段: