在運行時可以執行類型檢查以檢查對象的類型。類型轉換將對象強制轉換為不同的類型
is
和 !is
可以使用is
或者!is
來判斷實例是不是指定的類型
fun main() {var obj : Any = "cast"if (obj is String) {println(obj.length) // 4}obj = 123if (obj !is String) { print("Not a String") // Not a String} else {println(obj.length)}
}
智能轉換
正常情況下,當使用了is
或者!is
判斷實例類型時,如果返回的是true
則會自動轉成相應的類型,不需要再顯示的進行類型轉換了
fun main() {var obj : Any = "cast"if (obj is String) {println(obj.length) // 4}
// println(obj.length) // 報錯 - Unresolved reference: lengthif (obj !is String) returnprintln(obj.length)
}
fun main() {val x : Any = ""if (x !is String || x.length == 0) returnif (x is String && x.length > 0) {print(x.length) }
}
在when
中使用
when (x) {is Int -> print(x + 1)is String -> print(x.length + 1)is IntArray -> print(x.sum())
}
注意,只有當編譯器能夠保證變量在檢查和使用之間不會改變時,智能強制轉換才會起作用。
只能轉換在一下場景生效
變量類型 | 說明 |
---|---|
var 本地變量 | 一般都會生效,除了局部委托變量 |
var 類屬性 | 如果屬性是私有的、內部的,或者檢查是在聲明屬性的同一模塊中進行的,那么可以使用智能轉換。但是,智能轉換不能用于開放屬性或具有自定義 getter 的屬性。 |
val 本地變量 | 如果變量在檢查和使用之間沒有被修改,沒有被修改它的 lambda 捕獲,也不是本地委托屬性,那么就可以使用這個變量。 |
val 類屬性 | 永遠不會,因為變量可以在任何時候被其他代碼修改。 |
不安全的強制轉換
不安全的強制轉換通常會報錯,使用as
進行操作
fun main() {val str: Any = "cast"val s = str as Stringval i = str as Int //報錯 java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer
}
注意,不能使null
轉換成String
類型,如果有null
風險,需要添加?
fun main() {val str: Any? = nullval s1 = str as String?val s2 = str as String // 報錯 - java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
}
安全的強制轉換
如果要避免異常,可以使用as?
,如果轉換失敗則返回null
fun main() {val str: Any? = nullval s = str as? Stringprintln(s) // null
}