Kotlin smart cast with nullable variable

∥☆過路亽.° 提交于 2020-06-27 14:07:23

问题


When I'm trying to create the following code:

class SmartCast {
    var array: MutableList<Int>? = null

    fun processArray() {
        if (array != null && !array.isEmpty()) {
            // process
        }
    }
}

this error is shown:

Smart cast to 'MutableList' is impossible, because 'array' is a mutable property that could have been changed by this time

It's clear that the array variable can be changed to null in case of multi-threading. But if I use @Synchronized annotation, there is no way to mutate the variable in between array != null and !array.isEmpty().

@Synchronized
fun processArray() {

I'm wonder, why the compiler doesn't allow smart cast in synchronized blocks or maybe it's possible to specify somehow that my application is designed only for single-threaded mode?

UPDATE: According to the answers, I changed the code in the following way:

fun processArray() {
    array?.takeUnless { it.isEmpty() }?.also {
        for (elem in it)
            // process elements
    }
}

回答1:


why the compiler doesn't allow smart cast in synchronized blocks

Because this

But if I use @Synchronized annotation, there is no way to mutate the variable in between array != null and !array.isEmpty().

is wrong. @Synchronized means this method can't be called by two threads at the same time, but another thread which has access to the same instance is perfectly free to reassign array.

You also need to mark the setter as @Synchronized, in which case it really can't be changed at the moment. But trying to figure out exactly when smart casts are safe would lead to very complex rules, and minor changes in one method suddenly breaking smart casts in others. So the rules are conservative instead.




回答2:


Save the list to a local variable, and use that local variable. An elegant way to do that is to use the let function, and to combine it with the null-safe operator:

array?.let { 
    if (!it.isEmpty()) {
        // process it
    }
}

This is described in the idioms section of the getting started guide, BTW.




回答3:


Kotlin 1.3 introduced a function for that:

fun <T> Collection<T>?.isNullOrEmpty(): Boolean

So,

class SmartCast {
    var array: MutableList<Int>? = null

    fun processArray() {

        if(!array.isNullOrEmpty()){
            // processs
        }
    }
}

will compile.



来源:https://stackoverflow.com/questions/50885684/kotlin-smart-cast-with-nullable-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!