Kotlin称“无法进行智能投射,因为此时属性可能已更改". [英] Kotlin "Smart cast is impossible, because the property could have been changed by this time"

查看:96
本文介绍了Kotlin称“无法进行智能投射,因为此时属性可能已更改".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么我使用2号脚本时Android Studio显示错误. 我发现1和2之间没有区别.

Why Android Studio show error when I use No.2 script. I found no different between 1 and 2.

class Adapter {
    var nameList : ArrayList<String>? = null
}

class Program {
    private fun send() {
        val list: ArrayList<String> = ArrayList()
        val adapter = Adapter()

// Case 1
        var otherList = adapter.nameList
        if (otherList != null) {
            list.addAll(otherList) // <--- no error
        }

// Case 2
        if (adapter.nameList!=null) {
            list.addAll(adapter.nameList) // <--- Error here
            // Smart cast to 'kotlin.collections.ArrayList<String> /* = java.util.ArrayList<String> */' is impossible, because 'adapter.nameList' is a mutable property that could have been changed by this time
        }
    }
}

请解释这种情况

推荐答案

IDE应该向您发出警告,解释说在进行空检查之后,adapter.nameList可能已被另一个线程更改,并且在您调用list.addAll(adapter.nameList)adapter.nameList到那时实际上可能为空(再次,因为另一个线程可能已经更改了该值.这是竞争条件).

The IDE should give you a warning, explaining that after the null check, it's possible that adapter.nameList was changed by another thread, and that when you call list.addAll(adapter.nameList), adapter.nameList could actually be null by that point (again, because a different thread could have changed the value. This would be a race condition).

您有一些解决方案:

  1. nameList设为val,将其引用为final.由于它是最终的,因此可以保证另一个线程无法更改它.这可能不适合您的用例.

  1. Make nameList a val, which makes its reference final. Since it's final, it's guaranteed another thread can't change it. This probably doesn't fit your use case.

class Adapter {
    val nameList : ArrayList<String>? = null
}

  • 在执行检查之前创建名称列表的本地副本.因为它是本地副本,所以编译器知道另一个线程无法访问它,因此无法对其进行更改.在这种情况下,可以使用varval定义本地副本,但我建议使用val.

  • Create a local copy of name list before you do the check. Because it's a local copy, the compiler knows that another thread can't access it, and thus it can't be changed. The local copy could be defined with either a var or a val in this case, but I recommend val.

    val nameList = adapter.nameList
    if (nameList != null) {
        list.addAll(nameList)
    }
    

  • 使用Kotlin提供的一种实用程序功能来解决这种情况. let函数使用内联函数将其调用的引用复制为参数.这意味着它可以有效地编译为与#2相同的代码,但是更加简洁. 我更喜欢这种解决方案.

    adapter.nameList?.let { list.addAll(it) }
    

  • 这篇关于Kotlin称“无法进行智能投射,因为此时属性可能已更改".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆