KOTLIN中的智能强制转换与显式强制转换有何不同



最近我读到了由is运算符执行的智能强制转换,以及中用于显式强制转换的as或更好的as?运算符。

kotlin文档物种的用法差异如下:-

请注意,当编译器无法保证变量在检查和使用之间不会发生更改时,智能强制转换将不起作用更具体地说,智能强制转换根据以下规则适用:

  • val局部变量-总是局部委托属性除外;

  • val属性-如果属性是私有的、内部的或检查在声明属性的同一模块中执行。聪明的强制转换不适用于打开的属性或具有自定义getter;

  • var局部变量-如果变量在检查和用法,并没有在修改它的lambda中捕获,并且不是本地委托财产;

  • var属性-never(,因为变量可以在任何时候修改其他代码的时间(。

请注意,当编译器不能保证变量不能在检查和使用之间更改。

上面写的内容有点令人困惑,因为var变量可以在初始化后更改,而且我找不到一个例子可以清楚地了解语句的实际内容

无论如何,有人能让我们更容易更好地理解这一见解吗

as算子相比,is算子是否提供了一些优化优势(如果有的话(

智能强制转换的理念是帮助您避免使用asas?来显式强制转换已检查的内容。就上面的要点而言,这里有一些例子。

  • val局部变量-由于val是最终变量(不能更改(,在您进行检查后,变量可以进行智能强制转换,因为它不能再次更改
val a: Int? = 2
if (a is Int) {
// 'a' is smart cast to Int
val b = a * 2 // b is also Int
}
  • val属性-如果直接访问(通过默认的getter(,则可以进行智能强制转换。如果通过自定义getter,这并不是因为我们不知道它被修改了
class Test {
val a: Int? = 2;
}
class TestGetter {
val a: Int? = 2
get() = field * 2
}
// Usage
val test = Test()
val testGetter = TestGetter()
if (test.a is Int) {
// 'test.a' is smart cast to Int
val b = test.a * 2
}
if (testGetter.a is Int) {
// smart cast is impossible, 'testGetter.a' is still Int?
val b = testGetter.a * 2 // can't happen because we don't know whether 'a' was changed by the custom getter or not (the getter could give unstable values)
}
  • var局部变量-如果变量在检查和使用之间没有被修改,没有在修改它的lambda中捕获,并且不是局部委托属性
var a: Int? = 2
if (a is Int) {
// 'a' was not changed, so it can be smart cast to Int
val b = a * 2 // b is also Int
}
var c = 4
if (c is Int) {
c = null
// 'c' was changed between the check and the usage, we cannot smart cast it anymore
val b = c * 2 // won't work
}

var属性-代码中的其他东西总是可以修改var,所以智能强制转换不起作用。

class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a * 2 // won't work
}
}
}

就使用as而言,如果您查看最后一个示例:

class Example {
var a: Int? = 2
fun test1() {
if (a is Int) {
// smart cast is impossible because we don't know whether 'a' was changed by some other code/function
val b = a as Int * 2 // this WILL work because we forcefully cast it to Int, but if a is null there will be an exception in runtime
}
}
}

当您不确定var是否可以强制转换为某个值时,也可以使用as?。如果没有,它只会给你一个null。例如:

val a: Double = 2.0
val b = a as? String // 'b' will be 'String?', in this case initialized to 'null' since 'a' cannot be cast to it
val c: Int? = 2
val d = c as? Int // 'd' will be '2' but still 'Int?' since 'as?' always makes the variable nullable

希望这些例子能有所帮助,如果我需要进一步澄清的话,请告诉我。