#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>() }