为什么这个Kotlin代码仍然需要?访问会员?

时间:2017-06-01 01:18:02

标签: android kotlin

我在Kotlin课程中有以下功能:

private fun raiseResponse(ex: Exception, resObj: JSONObject) {
    if (_activity == null || _responseHandler == null) return

    _activity.runOnUiThread {
        _responseHandler.invoke(ex, resObj)
    }
}

_activity_responseHandler都定义为:

var _activity: Activity? = null
var _responseHandler: ((Exception, JSONObject) -> Unit)? = null

但是,调用runOnUiThread的行只会在我使用?.而不是.时进行编译。

我尝试过谷歌搜索,但我担心我的术语不足。我假设raiseResponse第一行的空检查足以确保?.不必要吗?

1 个答案:

答案 0 :(得分:4)

首先,请注意检查和使用情况两次获取属性的值。由于_activityvar,因此可以在检查和使用之间重新分配(可能由另一个线程)。使用属性值不是空安全的,因为它可能不是已检查的值,编译器要求您再次检查该值。

换句话说,编译器不能smart-cast _activity为非可空类型。

你可以通过将值存储在局部变量中来解决这个问题(它不能从外部更改,因此编译器可以证明它的值相同):

val activity = _activity
if (activity == null || _responseHandler == null) return

activity.runOnUiThread {
    _responseHandler.invoke(ex, resObj)
}

或者,等效地使用像?.let { ... }这样的成语:

_activity?.let { activity ->
    if (_responseHandler == null) return

    activity.runOnUiThread { // safe, because it is surely the same value
        _responseHandler.invoke(ex, resObj)
    }
} ?: return

另见: