is和!is操作符
我們可以通過(guò)is操作符和!is操作符來(lái)檢查一個(gè)對(duì)象是否是目標(biāo)類型:
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // same as !(obj is String)
print("Not a String")
}
else {
print(obj.length)
}
職能轉(zhuǎn)換(Smart Casts)
許多情況下,Kotlin是不用使用強(qiáng)制類型轉(zhuǎn)換操作的,因?yàn)榫幾g器會(huì)跟蹤不可變值的is檢查操作,并會(huì)在需要的時(shí)候自動(dòng)插入(安全的)類型轉(zhuǎn)換操作:
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
如果否定檢查導(dǎo)致返回,編譯器足夠聰明地知道轉(zhuǎn)換是安全的:
if (x !is String) return
print(x.length) // x is automatically cast to String
或者在&&和||操作符的右側(cè):
// x is automatically cast to string on the right-hand side of `||`
if (x !is String || x.length == 0) return
// x is automatically cast to string on the right-hand side of `&&`
if (x is String && x.length > 0) {
print(x.length) // x is automatically cast to String
}
如此只能的轉(zhuǎn)換也可以用于when表達(dá)式和while循環(huán)中:
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
注意:當(dāng)編譯器不能保證變量在檢查和使用之間不會(huì)發(fā)生改變的時(shí)候,職能轉(zhuǎn)換則是不能用的。也就是說(shuō),智能轉(zhuǎn)換的使用需要依據(jù)以下規(guī)則:
- val局部變量,總是可以。
- val屬性:若屬性是
private或internal類型的,或者類型檢查是執(zhí)行在屬性聲明的同一模塊中的,則可以使用智能轉(zhuǎn)換。智能轉(zhuǎn)換不能用于open屬性或者具有自定義getter的屬性。 - var局部變量:如果變量在檢查和使用之間沒(méi)有修改,且沒(méi)有被毀修改它的λ表達(dá)式捕獲,則可以使用。
- var屬性:總是不可以。(因?yàn)樵撟兞康闹悼梢栽谌我鈺r(shí)刻被任意代碼修改)
非安全轉(zhuǎn)換操作("Unsafe" cast operator)
通常,如果一個(gè)轉(zhuǎn)換不能夠完成的話講拋出一個(gè)異常。因此,我們稱之為非安全的。這種非安全的轉(zhuǎn)換在Kotlin中通過(guò)中綴操作符as實(shí)現(xiàn):
val x: String = y as String
注意:null不能被轉(zhuǎn)換為String,因?yàn)樵擃愋褪遣荒転?code>null的。也就是說(shuō),如果變量y是null,則上述代碼將會(huì)拋異常。為了匹配Java轉(zhuǎn)換語(yǔ)義,在轉(zhuǎn)換右邊必須是可null類型:
val x: String? = y as String?
安全轉(zhuǎn)換操作("Safe" (nullable) cast operator)
為了避免異常的拋出,可以使用安全轉(zhuǎn)換操作符as?,當(dāng)轉(zhuǎn)換失敗的時(shí)候,將會(huì)返回null
val x: String? = y as? String
注意:盡管as?右側(cè)是一個(gè)非null類型String,但其轉(zhuǎn)換結(jié)果則可以是null。