【问题标题】:How is smart cast different from explicit cast in KOTLIN智能转换与 KOTLIN 中的显式转换有何不同
【发布时间】:2020-11-22 14:10:57
【问题描述】:

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

kotlin 文档将它们的用法区别如下:-

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

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

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

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

  • var 属性 - 从不(因为可以随时修改变量 其他代码的时间)。

请注意,当编译器无法保证时,智能转换不起作用 变量不能在检查和使用之间改变。

上面写的有点混乱,因为var变量可以在初始化后更改,我找不到可以说明该语句实际洞察力的示例。

无论如何,任何人都可以更轻松地更好地理解这种洞察力吗?

如果有的话,is 运算符是否比 as 运算符提供了一些优化优势?

【问题讨论】:

    标签: android performance kotlin optimization casting


    【解决方案1】:

    智能转换的想法是帮助您避免使用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?。如果没有,它只会给你一个空值。例如:

    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
    

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

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多