简体   繁体   中英

how to use a function with Boolean? return type in an if statement in Kotlin

I'm using methods (for example the method containsKey of MutableList) that returns a true false. Since the function is written in java, Kotlin refers to return type as Boolean? and this the reason i'm getting a compilation error: "Required: Boolean, Found: Boolean?". I must say in some case (don't know why) using the method is ok and sometimes it return the error above. Can someone guess what is the reason?

My code:

val gamesPerCountriesMap = mutableMapOf<String,MutableMap<Long, List<AllScoresGameObj>>>()

if (countryName != null  && countryName != "" && !gamesPerCountriesMap.containsKey(countryName))
{
    gamesPerCountriesMap.put(countryName, mutableMapOf<Long,List<AllScoresGameObj>>())
}

if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))
{
    gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
}

First if is compiled the second one make the error:

Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Boolean?

if I remove the ! in the beginning of the second if i will different error:

Type mismatch: inferred type is Boolean? but Boolean was expected

After reading all the suggestion i wrote the following code:

gamesPerCountriesMap.get(countryName)?.let {
    if (!gamesPerCountriesMap.containsKey(it))
    {
        gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
    }
}

What do you think?

You have to take care of the nullable

mutableMapOf<String?, MutableMap...

That means the keys can be a null String

If the countryName is a field, then

countryName?.let {
   //your validation here
}

Fields can be changed so compiler doesn't know if it nullable or not.

or

val safeName = countryName ?: return

Basically in the Java, Boolean is an object type. It has 3 possible values: true, false, and null. Since kotlin have null safety feature, using ? in object type, like Boolean?, that's why it's asking you to make sure that the data isn't null. So for your code:

 if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))
                        {
                            gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>())
                        }

It checks if the get method returning null or not, if it's not, then it proceed to the next function containsKey . If it's null, then it's pass the if statement. For the non-null asserted, it's force the Boolean? data type into the Boolean . This can be use if you're sure that the data must not be null, else it'll break your program, because you're accessing function in a null data. So it depends on your choice, you can use ? or !! if you sure it's not null.

if (!gamesPerCountriesMap.get(countryName)?.containsKey(competitionId))

will check if the item is true, false or null. The "if" statement requires true or false. This is why you see "Type mismatch: inferred type is Boolean? but Boolean was expected"

if (gamesPerCountriesMap.get(countryName) == null || !gamesPerCountriesMap.get(countryName)!!.containsKey(competitionId))

if the item is null, or if not null but also does not contain competitionID, then do this, so thats what you want to use.

Edit:

You also want to allow the map to contain a null value like this:

val gamesPerCountriesMap = mutableMapOf<String,MutableMap<Long, List<AllScoresGameObj>>?>()

the "?" at the end allows the nested MutableMap to be null.

You can reduce it like:

if (!countryName.isNullOrEmpty()) {
    gamesPerCountriesMap.getOrPut(countryName) { mutableMapOf<Long,List<AllScoresGameObj>>() }
}

gamesPerCountriesMap[countryName]!!.getOrPut(competitionId) { listOf<AllScoresGameObj>() }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM