Как конвертировать String в Long в Kotlin и не сойти с ума: разбор типичных ошибок
Каждый разработчик на Kotlin рано или поздно сталкивается с задачей: нужно взять строку, которую ввёл пользователь, пришёл ответ от API или прочитался файл, и превратить её в число типа Long. Казалось бы, что может быть проще? Но именно здесь, на ровном месте, новички (да и опытные программисты) совершают ошибки, которые приводят к падениям приложения, пустым экранам и бессонным ночам дебага.
В этой статье мы разберём пять самых частых ошибок при конвертации String в Long в Kotlin. Вы узнаете не только как их исправить, но и как писать код, который не сломается при первом же невалидном вводе. Поехали!
Ошибка №1: Наивное использование toLong() без обработки исключений
Самый прямолинейный способ — вызвать метод toLong() у строки. Да, это работает, но только если строка содержит корректное число. В противном случае — привет, NumberFormatException!
val userInput = "123abc"
val number: Long = userInput.toLong() // Вылетит NumberFormatException!
Почему это плохо? Исключение в рантайме — это всегда риск. Если ваше приложение не обработает его, пользователь увидит краш.
Как исправить? Используйте try-catch или, что ещё лучше, безопасную альтернативу — toLongOrNull().
val userInput = "123abc"
val number: Long? = userInput.toLongOrNull() // Вернёт null, никакого исключения
println(number) // null
Метод toLongOrNull() — ваш спаситель. Если строку нельзя преобразовать, он просто вернёт null, и вы спокойно обработаете этот случай.
Ошибка №2: Игнорирование null и пустых строк
В Kotlin типы явно делятся на nullable и non-null. Если вы попытаетесь вызвать toLong() у строки, которая может быть null, компилятор вас не пропустит. Но есть подвох: пустая строка ("") — это не null, и она тоже вызовет исключение.
val nullableString: String? = null
// nullableString.toLong() // Ошибка компиляции: только safe (?.) или non-null asserted (!!.) вызовы
val emptyString = ""
emptyString.toLongOrNull() // null, всё хорошо
Практический совет: Всегда проверяйте строку на пустоту или используйте toLongOrNull() в паре с элвис-оператором ?:.
fun parseUserAge(input: String?): Long {
return input?.toLongOrNull() ?: 0L // Если null или не число — вернём 0
}
Такой подход делает код идиоматичным и безопасным.
Ошибка №3: Забываем про пробелы и невидимые символы
Пользователи — существа непредсказуемые. Они могут случайно поставить пробел перед числом или в конце. Строка из файла может содержать символы перевода строки \n. Метод toLongOrNull() не умеет обрезать строку — он ожидает, что строка состоит только из цифр (и, возможно, знака минус).
val dirtyString = " 42 "
dirtyString.toLongOrNull() // null, потому что есть пробелы
Решение: Всегда вызывайте trim() перед конвертацией.
val cleanString = dirtyString.trim()
val number: Long? = cleanString.toLongOrNull()
println(number) // 42
Это один из самых простых и эффективных способов избежать багов. Запомните правило: trim before you convert.
Ошибка №4: Проблемы с локализацией и разделителями
В разных странах числа записывают по-разному. В США и России для разделения тысяч используют запятую (1,234) или пробел (1 234), а десятичные дроби отделяют точкой. В Европе всё наоборот: запятая — это десятичный разделитель. Kotlin по умолчанию ожидает «чистый» числовой формат без разделителей.
val usNumber = "1,234"
usNumber.toLongOrNull() // null — запятая недопустима
val germanNumber = "1.234"
germanNumber.toLongOrNull() // null — точка воспринимается как десятичный разделитель, но дробная часть не указана
Как быть? Если вы работаете с пользовательским вводом или данными из разных источников, предварительно очистите строку от всех нечисловых символов, кроме знака минус.
fun cleanAndParse(input: String): Long? {
val cleaned = input.replace(Regex("[^\\d-]"), "") // Удаляем всё, кроме цифр и минуса
return cleaned.toLongOrNull()
}
println(cleanAndParse("1,234")) // 1234
println(cleanAndParse("1 234")) // 1234
println(cleanAndParse("1.234")) // 1234 (если это не дробное число)
Важно: этот метод подходит только для целых чисел. Если вы ожидаете дробные числа, логика будет сложнее.
Ошибка №5: Игнорирование переполнения (overflow)
Диапазон типа Long в Kotlin — от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Если строка содержит число за пределами этого диапазона, toLong() или toLongOrNull() выбросят NumberFormatException (или вернут null).
val hugeNumber = "99999999999999999999999"
println(hugeNumber.toLongOrNull()) // null — переполнение
Что делать? Если вы ожидаете потенциально большие числа, рассмотрите использование BigInteger из Java или библиотек, которые поддерживают произвольную точность. Или, как минимум, проверяйте длину строки перед конвертацией.
fun safeParseLong(input: String): Long? {
val trimmed = input.trim()
if (trimmed.length > 19) return null // Максимум 19 цифр для Long (с учётом минуса)
return trimmed.toLongOrNull()
}
Это не панацея, но хорошая защита от наивных ошибок.
Итоговый чек-лист: как правильно конвертировать String в Long в Kotlin
Давайте соберём все рекомендации в один универсальный подход. Вот функция, которая учитывает все пять ошибок:
fun parseStringToLong(input: String?): Long? {
if (input == null) return null
val cleaned = input.trim().replace(Regex("[^\\d-]"), "")
if (cleaned.isEmpty() || cleaned == "-") return null
return cleaned.toLongOrNull()
}
// Примеры использования