Я хотел создать свой собственный класс Map, который допускает только класс Number
(т. е. Int
, Long
, Double
, ...). Кроме того, если значение записи станет нулевым, эта запись будет автоматически удалена с карты. Поскольку я не знаком с дженериками в Котлине, имейте в виду, что я, возможно, написал класс правильно, но ниже приведен код, который я написал.
class PositiveMap<K, V> : HashMap<K, V>() where V : Number {
override fun put(key: K, value: V): V? {
val isZero = when (value) {
is Byte -> value == 0.toByte()
is Short -> value == 0.toShort()
is Int -> value == 0
is Long -> value == 0L
is Float -> value == 0f
is Double -> value == 0.0
is BigInteger -> value == BigInteger.ZERO
is BigDecimal -> value == BigDecimal.ZERO
else -> false
}
// Don't put value at all if value was zero, and there was no such key
if (!containsKey(key) && isZero) {
return null
}
val old = super.put(key, value)
// Remove entry if value turned out to be zero
if (isZero) {
remove(key)
Однако IDE предупреждает меня, что в каждом случае проверка того, равен ли value
нулю, всегда возвращает false.
Я попытался добавить немного грязную проверку, как показано ниже, но IDE предупреждает, что value
действительно является Number
классом.
Поэтому я просто решил создать код тестового модуля и проверить, работает он нормально или нет.
class TestUnit {
companion object {
@JvmStatic
fun main(args: Array<String>) {
// Putting PositiveMap<String, String> shows error as intended
val map = PositiveMap<String, Long>()
map["hello"] = 1L
println(map["hello"])
println(map.containsKey("hello"))
map["hello"] = (map["hello"] ?: 0L) - 1L
println(map["hello"])
println(map.containsKey("hello"))
}
}
}
Вывод был как ниже
1
true
null
false
Этот вывод заставил меня почувствовать, что IDE просто показывает ложные срабатывания. Однако, как я уже говорил выше, я не знаком с дженериками, поэтому не могу себя уверить, что это баг IDE.
Я использую IntelliJ IDEA, ниже приведена информация о версии.
и ниже представлена версия Kotlin, которую я использую
Это ложное предупреждение (вероятно, ошибка) или есть ли способ удалить предупреждение, которое выдает IDE?
Обновлено:
Я вместо этого попробовал поставить value <= 0
для каждого случая, тогда предупреждения убираются. Однако я все еще задаюсь вопросом, почему проверка точного нуля предупреждает меня
проблема в том, что компилятор не может выполнять интеллектуальное приведение value
в этих ветках. Если вы переключитесь на новый компилятор K2 (который стал стабильным с Kotlin 2.0.0), предупреждение исчезнет.
Спасибо всем, ребята, как упоминал @user2340612, я попробовал компилятор K2, и он удалил предупреждения! Вы можете написать ответ, чтобы вас приняли, или я напишу ответ сам.
Похоже, что старая версия компилятора Kotlin (используемая IntelliJ для проверки кода) не способна реализовать, что в этих when
ветках переменную value
можно безопасно привести к соответствующему типу. Вероятно, это вызвано ограничением существующей версии компилятора и, похоже, исправлено в новом компиляторе K2.
Если вы включите режим K2 в IDE, вы увидите, что переменная value
будет автоматически приведена к правильному типу, и соответствующее предупреждение исчезнет.
Обратите внимание: несмотря на то, что компилятор K2 стабилен, IntelliJ IDEA в настоящее время все еще использует старый компилятор для подсветки синтаксиса, проверки и т. д., поскольку «режим K2» все еще находится в альфа-версии — см. здесь. Вы можете включить «режим K2» в IntelliJ 2024.1 (или новее), но имейте в виду, что
Производительность и стабильность подсветки кода и завершения кода были значительно улучшены, но пока поддерживаются не все функции IDE.
Я обнаружил, что сам компилятор Kotlin (то есть командная строка kotlinc
) не выдает никаких предупреждений, даже в более ранних версиях. Эти предупреждения выдает только IDE.
правильно. То, что выделяет IDE, является результатом «проверки», поэтому технически это подсказка IDE, а не предупреждение компилятора. Однако IDE использует встроенный компилятор для оценки этих проверок, поэтому фактическое «исправление» этой проблемы состоит в том, чтобы просто включить «режим K2» в IDE. Я обновил свой ответ, чтобы прояснить этот момент.
Скорее всего, это просто ошибка IntelliJ.