как использовать функцию с логическим значением? возвращаемый тип в операторе if в Kotlin

#java #android #kotlin

#java #Android #kotlin

Вопрос:

Я использую методы (например, метод containsKey из MutableList ), который возвращает значение true false . Поскольку функция написана на Java, Kotlin ссылается на возвращаемый тип как логический? и по этой причине я получаю ошибку компиляции: «Требуется: логическое значение, найдено: логическое значение?». Я должен сказать, что в некоторых случаях (не знаю почему) использование метода в порядке, и иногда он возвращает ошибку выше. Может кто-нибудь догадаться, в чем причина?

Мой код:

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

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

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

Первый if компилируется, второй выдает ошибку:

Только безопасные (?.) или ненулевые (!!.) Вызовы разрешены для обнуляемого получателя типа Boolean?

если я удалю!в начале второго if у меня будет другая ошибка:

Несоответствие типов: предполагаемый тип является логическим? но логическое значение ожидалось

После прочтения всех предложений я написал следующий код:

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

Что вы думаете?

Комментарии:

1. Показать фрагмент кода

2. Сделано две секунды назад 🙂

3. Фрагмент ошибки, код, в котором вы получаете эту логическую ошибку, также указывает на это

4. Добавлены две возможные ошибки snippest

5. Я нашел решение, но я не знаю, почему и как оно решает проблему… Если я добавлю == false , обе ошибки исчезнут

Ответ №1:

Вы должны позаботиться о значении null

 mutableMapOf<String?, MutableMap...
  

Это означает, что ключи могут быть нулевой строкой

Если это countryName поле, то

 countryName?.let {
   //your validation here
}
  

Поля могут быть изменены, чтобы компилятор не знал, обнуляемо оно или нет.

или

 val safeName = countryName ?: return
  

Комментарии:

1. проблема не связана с containsKey, который может возвращать логическое значение? ? Потому что следующий код все еще содержит ошибку: countryName? .пусть { if (!gamesPerCountriesMap.get(название страны)? .containsKey(competitionId)) } Я думаю, что проблема, связанная с тем фактом, что метод get может возвращать null let, может быть использована следующим образом (и это работает): gamesPerCountriesMap.get(название страны)? .пусть { if (!gamesPerCountriesMap.containsKey(it))

Ответ №2:

В основном в Java Boolean — это тип объекта. Он имеет 3 возможных значения: true, false и null. Поскольку у kotlin есть функция безопасности null, использующая ? тип объекта in, например, Boolean? , вот почему он просит вас убедиться, что данные не являются нулевыми. Итак, для вашего кода:

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

Он проверяет get , возвращает ли метод null или нет, если это не так, то он переходит к следующей функции containsKey . Если значение равно null, то передается оператор if. Для ненулевого утверждения он принудительно вводит Boolean? тип данных в Boolean . Это можно использовать, если вы уверены, что данные не должны быть нулевыми, иначе это нарушит работу вашей программы, потому что вы обращаетесь к функции с нулевыми данными. Так что это зависит от вашего выбора, вы можете использовать ? or !! , если вы уверены, что это не null .

Комментарии:

1. как использовать ?

2. Как и приведенный выше фрагмент кода, gamesPerCountriesMap.get(countryName)?.put(competitionId, listOf<AllScoresGameObj>()) . Это означает, что если это gamesPerCountriesMap.get(countryName) возвращает значение not null, оно переходит к методу put, иначе оно останавливается там.

Ответ №3:

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

проверит, является ли элемент true, false или null. Оператор «if» требует true или false. Вот почему вы видите «Несоответствие типов: предполагаемый тип является логическим? но логическое значение ожидалось «

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

если элемент имеет значение null или if not null, но также не содержит competitionID, то сделайте это, так что это то, что вы хотите использовать.

Редактировать:

Вы также хотите, чтобы карта содержала нулевое значение, подобное этому:

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

«?» в конце позволяет вложенной изменяемой карте иметь значение null.

Комментарии:

1. Почему вы говорите: » вернет false, если первая сторона равна нулю, так что это то, что вы хотите использовать. «. Каков порядок проверки? если get возвращает null, то null проверяется на true и возвращает false, а затем ! изменит все if на true. Не так ли?

2. Оператор if требует true или false и не может быть определен с помощью null . «Несоответствие типов: предполагаемый тип является логическим? но ожидалось логическое значение «. Вы даете ему логическое значение? но для этого требуется логическое значение. Добавление к нему «== true» превратит его в логическое значение, потому что, если вы получите значение null, значение null не равно true, поэтому оно вернет false .

3. не забывайте ! в вашем объяснении. это превратит false в true

4. О да, я понимаю, извините. Я это исправил, вам просто нужно добавить скобки. if (!(gamesPerCountriesMap.get(название страны)? .containsKey(competitionId) == true))

5. Как это помогает? тем не менее, если метод get возвращает значение null, то значение null сравнивается с true и все выражение (gamesPerCountriesMap.get(countryName)? .containsKey(competitionId) == true) имеет значение false . Тогда ! при этом он примет значение true

Ответ №4:

Вы можете уменьшить его следующим образом:

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

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