为什么这个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足以确保?. 是不必要的?

首先,请注意检查和使用情况会得到两次财产的价值。 由于_activity是一个var ,它可以在检查和使用之间重新分配(可能由另一个线程)。 使用属性值不是无效的,因为它可能不是被检查的值,编译器要求你再次检查值。

换句话说,编译器不能将 _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 

也可以看看:

  • 最好的方法来处理这种情况下,“聪明的演员是不可能的”

  • 科特林,聪明的演员是不可能的,因为复杂的表达

  • 在Kotlin中,处理可空值的惯用方式是什么,引用或转换它们