is和!is操作符
我们可以通过is
操作符和!is
操作符来检查一个对象是否是目标类型:
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // same as !(obj is String)
print("Not a String")
}
else {
print(obj.length)
}
职能转换(Smart Casts)
许多情况下,Kotlin是不用使用强制类型转换操作的,因为编译器会跟踪不可变值的is
检查操作,并会在需要的时候自动插入(安全的)类型转换操作:
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
如果否定检查导致返回,编译器足够聪明地知道转换是安全的:
if (x !is String) return
print(x.length) // x is automatically cast to String
或者在&&
和||
操作符的右侧:
// 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
}
如此只能的转换也可以用于when
表达式和while
循环中:
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
注意:当编译器不能保证变量在检查和使用之间不会发生改变的时候,职能转换则是不能用的。也就是说,智能转换的使用需要依据以下规则:
- val局部变量,总是可以。
- val属性:若属性是
private
或internal
类型的,或者类型检查是执行在属性声明的同一模块中的,则可以使用智能转换。智能转换不能用于open
属性或者具有自定义getter
的属性。 - var局部变量:如果变量在检查和使用之间没有修改,且没有被毁修改它的λ表达式捕获,则可以使用。
- var属性:总是不可以。(因为该变量的值可以在任意时刻被任意代码修改)
非安全转换操作("Unsafe" cast operator)
通常,如果一个转换不能够完成的话讲抛出一个异常。因此,我们称之为非安全的。这种非安全的转换在Kotlin中通过中缀操作符as
实现:
val x: String = y as String
注意:null
不能被转换为String
,因为该类型是不能为null
的。也就是说,如果变量y
是null
,则上述代码将会抛异常。为了匹配Java转换语义,在转换右边必须是可null
类型:
val x: String? = y as String?
安全转换操作("Safe" (nullable) cast operator)
为了避免异常的抛出,可以使用安全转换操作符as?
,当转换失败的时候,将会返回null
val x: String? = y as? String
注意:尽管as?
右侧是一个非null
类型String
,但其转换结果则可以是null
。