2017-06-01 121 views
1

我有一個科特林級以下功能:爲什麼這個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的第一行我的空檢查足以確保?.是不必要的?

回答

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 

參見:

+0

啊好非常好。這是有道理的,'_activity'的範圍意味着它可以在檢查之後但在調用之前被修改。我認爲這可能是這個,但在確認之前不願意做一堆局部變量。 –

相關問題