当前位置: 首页 > 知识库问答 >
问题:

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

仲孙鸿畴
2023-03-14

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

kotlin docs的种类及其使用差异如下:-

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

>

  • val局部变量-始终不包括局部委托属性;

    val属性-如果属性是私有的或内部的,或者检查是在声明属性的同一模块中执行的。智能强制转换不适用于打开的属性或具有自定义获取器的属性;

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

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

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

    上面写的有点混乱,因为<code>var</code>变量可以在初始化后更改,我找不到一个例子可以清楚说明语句的实际含义。

    无论如何,有没有人能更容易更好地理解这个观点?

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

  • 共有1个答案

    勾裕
    2023-03-14

    智能投射的想法是帮助您避免使用 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 local variables-如果变量在检查和使用之间未被修改,则不会在修改它的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
            }
        }
    }
    

    您还可以使用as?当您不确定var是否可以强制转换为某些内容时。如果不是,它只会给您一个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
    

    希望这些例子有所帮助,让我知道我是否需要进一步澄清一些事情。

     类似资料:
    • 以下代码在C++11中编译成功: 它包括用于现代C++的JSON。一个工作示例在这个Wandbox中。 JSON变量被隐式转换为字符串。但是,如果我取消最后一行的注释,这是一个显式转换,它将无法编译。这里的编译结果。 除了这个json库的特殊细微差别之外,如何编写一个类,使隐式转换工作,而显式转换不工作? 是否有某种构造函数限定符允许这种行为?

    • 我的困难是 如何修复函数SortByTotal中的任何错误? 1.1错误:(32,51)Kotlin:无法智能强制转换为“OrderProcessing.OrderNode”,因为“Run.Next”是一个复杂的表达式 我明白有很多错误,回答其中的任何一个部分或者给我一些暗示已经很感激了。谢谢你的好意。 我的代码如下: 涉及的类:

    • 问题内容: “隐式转换”和“显式转换”有什么区别?Java和C ++的区别是否不同? 问题答案: 显式转换是您使用某种语法 告诉 程序进行转换的地方。例如(在Java中): 隐式转换是在没有任何语法的情况下进行转换的地方。例如(在Java中): 应该注意的是(在Java中)涉及原始类型的转换通常涉及某种表示形式的更改,并且可能导致精度降低或信息丢失。相比之下,仅涉及引用类型的转换不会更改基本表示形

    • 问题内容: 您能告诉我SQL Server中隐式转换和显式转换之间的区别吗? 我已经用谷歌搜索过,但是我听不懂。 问题答案: 当您在查询中显式使用or关键字时,就会发生显式转换。 当表达式中的数据类型不同时,SQL Server将根据数据类型优先级的规则自动将其强制转换,从而进行隐式转换。 例如,nvarchar的优先级高于varchar 第二个执行计划显示谓词为 在这种情况下,显式转换和隐式转换

    • 为什么当我使用No.2脚本时Android Studio显示错误。我发现1和2之间没有区别。 请解释这个案例

    • 数字的Number类型和日期Date类型的格式化是默认安装了的,包括@NumberFormat注解和@DateTimeFormat注解。如果classpath路径下存在Joda Time依赖,那么完美支持Joda Time的时间格式化库也会被安装好。如果要注册定制的格式化器或转换器,请覆写addFormatters方法: @Configuration @EnableWebMvc public cl