is and !is operators
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
核心原理
编译器自动跟踪类型检查结果,无需手动强制转换,直接使用目标类型的属性和方法。
fun demo(x: Any) {
if (x is String) {
print(x.length) // 编译器自动将 x 转换为 String 类型
}
}
支持的控制流
if条件:通过is或!is检查后,块内自动转换。when表达式:根据不同类型分支自动转换。
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
• while 循环:只要类型检查条件成立,循环内保持转换状态。
特殊场景
逻辑操作符(&&/||)
- 左侧为类型检查时,右侧自动转换。
if (x is String && x.length > 0) {
print(x.length) // x 自动转换为 String
}
if (x !is String || x.length == 0) return // x 在右侧自动转换为 String
变量提取
将类型检查结果存入布尔变量,仍可触发智能转换。
fun petAnimal(animal: Any) {
val isCat = animal is Cat
if (isCat) {
animal.purr() // 编译器通过 isCat 推断 animal 是 Cat 类型
}
}
类型转换操作符
不安全转换(as)
- 语法:
obj as Type,若转换失败抛出ClassCastException。 - 注意:若目标类型不可为空(如
String),源对象为null时也会抛异常。
val x: String = y as String // 若 y 为 null 或非 String 类型,抛出异常
- 安全用法:搭配可空类型使用。
val x: String? = y as String? // 若 y 为 null,x 为 null;若 y 非 String,抛异常
安全转换(as?)
- 语法:
obj as? Type,转换失败返回null,不抛异常。 - 应用场景:处理可能转换失败的情况,避免程序崩溃。
val x: String? = y as? String // 若 y 非 String 或为 null,x 为 null
其他重要场景
- 内联函数(Inline Functions)中的智能转换
内联函数会将 lambda 代码直接嵌入调用处,编译器可保证变量引用不会 “泄漏”,因此可对 lambda 中捕获的变量进行智能转换。
inline fun <T> processIfNotNull(obj: T?, action: (T) -> Unit) {
if (obj != null) {
action(obj) // 智能转换 obj 为非空类型
}
}
fun runProcessor() {
val processor: Processor? = getProcessor()
processIfNotNull(processor) { proc ->
proc.process() // 直接调用,无需安全操作符
}
}
- 异处理中的智能转换
try 块中若变量被赋值为非空,编译器会记住其类型;若变量在 try 块中被设为 null,则取消智能转换。
catch 块中变量恢复为可空类型,需使用安全操作符(?.)。
fun testString() {
var stringInput: String? = "" // 智能转换为 String
try {
println(stringInput.length) // 非空,直接访问
stringInput = null // 取消智能转换,变为 String?
// ...
} catch (e: Exception) {
println(stringInput?.length) // 需用安全操作符
}
}