智能类型转换是Kotlin中的一种机制,当编译器在检查某个特定类型或null后自动"降低"类型。这允许在没有显式转换的情况下使用转换后类型的属性和方法。
fun demo(x: Any) { if (x is String) { println(x.length) // x自动转换为String } }
适用于:
is / !is操作符(例如,在if或when中)if (x != null))when表达式不适用于:
val str: String? = getString() if (str != null) println(str.length) // 智能转换
val something: Any get() = fetch() if (something is String) { println(something.length) // 错误:智能转换不可用 }
在方法内部可以依靠开放或var类的属性进行智能转换吗?
不可以!智能转换仅适用于局部变量和final类中的val属性。对于开放(open)或var属性,编译器不确定值是否可能被其他线程或子类更改。对此需要手动转换或使用局部变量。
open class Base { open var maybeString: Any? = "abc" fun check() { if (maybeString is String) { // println(maybeString.length) // 错误:智能转换不可用 val asString = maybeString as String println(asString.length) // 显式转换 } } }
故事
在一个项目中,用于屏幕逻辑的模型数据使用了开放的var属性。程序员在检查if(model is SomeType)后依赖智能转换,然而在编译时不得不手动转换所有类型,这降低了可读性,并增加了重复代码,因为不知道智能转换对var/open的限制。
故事
通过getter(例如,通过委托或验证)获取数据时,智能转换未能成功。开发者不明原因,花费数小时调试,直到发现编译器不对这些getter应用智能转换,因为它们在调用之间可能返回不同的值。
故事
在处理可空值时,通过if(obj != null)智能转换在分支内可以工作,但在代码并行化时在保证范围外出现了NullPointerException。这显示了对智能转换的局部作用及在处理可空变量时多线程场景的特殊性的理解不足。