1. 程式人生 > >Kotlin 型別的檢查與轉換“is”與“as”

Kotlin 型別的檢查與轉換“is”與“as”

1,是與!是操作符

可以我們在執行時通過使用  is 操作符或其對劃線部分形式  !is 來檢查物件是否符合給定型別:

if (obj is String) {
    print(obj.length)
}

if (obj !is String) { // 與 !(obj is String) 相同
    print("Not a String")
}
else {
    print(obj.length)
}
  • 1
  • 2
  • 3
  • 4
  • 6
  • 7
  • 8
  • 9
  • 10

2,智慧轉換

在許多情況下,不需要在Kotlin中使用顯式轉換操作符,因為編譯器跟蹤不可變變的is-檢查以及顯式轉換,並在需要時自動插入(安全的)轉換:

fun demo(x: Any) {
    if
(x is String) { print(x.length) // x 自動轉換為字串 } }
  • 1
  • 2
  • 3
  • 4

編譯器足夠聰明,能夠知道如果反向檢查導致返回那麼該轉換是安全的:

  if (x !is String) return
    print(x.length) // x 自動轉換為字串
  • 1
  • 2

或者在&&和|| 的右側:

 // `||` 右側的 x 自動轉換為字串
    if (x !is String || x.length == 0) return

    // `&&` 右側的 x 自動轉換為字串
    if (x is String && x.length
> 0) { print(x.length) // x 自動轉換為字串 }
  • 1
  • 2
  • 3
  • 4
  • 6
  • 7

這些智慧轉換用於when-表示式和while-迴圈也一樣:

when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}
  • 1
  • 2
  • 3
  • 4

請注意,當編譯器不能保證變數在檢查和使用之間不可改變時,智慧轉換不能用。更具體地,智慧轉換能否適用根據以下規則:

  • val區域性變數 - 總是可以;
  • val屬性 - 如果屬性是private或internal,或者該檢查在宣告屬性的同一模組中執行。智慧轉換不適用於open的屬性或者具有自定義getter的屬性;
  • var區域性變數 - 如果變數在檢查和使用之間沒有修改,並且沒有在會修改它的lambda中捕獲;
  • var屬性 - 決不可能(因為該變數可以隨時被其他程式碼修改)。

3,“不安全的”轉換操作符

通常,如果轉換是不可能的,轉換操作符會丟擲一個異常。因此,我們稱之為不安全的.Kotlin中的不安全轉換由中綴操作符as(參見operator precedence)完成:

val x: String = y as String
  • 1

請注意,null不能轉換為String因該型別不是可空的,即如果y為空,上面的程式碼會丟擲一個異常。為了匹配Java轉換語義,我們必須在轉換右邊有可空型別,就像:

val x: String? = y as String?
  • 1

4,“安全的”(可空)轉換操作符

為了避免丟擲異常,可以使用安全轉換操作符作為?,它可以在失敗時返回null:

val x: String? = y as? String
  • 1

請注意,儘管事實上?的右邊是一個非空型別的String,但是其轉換的結果是可空的。