Как преобразовать строку в тип Long в Kotlin? Безопасные способы и обработка ошибок
Всем привет! Я только начал изучать Kotlin после Java, и у меня возникла проблема с преобразованием строки в число типа Long. Мне нужно прочитать числовое значение из текстового поля в приложении и выполнить с ним арифметические операции.
Вот пример моего кода:
val input = "1234567890123"
val number: Long = input.toLong()
println(number * 2)
Это работает, когда строка гарантированно содержит корректное число. Но что, если пользователь введёт что-то вроде "abc123" или "12.34"? Тогда программа вылетает с NumberFormatException. В Java я использовал try-catch или проверял через Long.parseLong, но в Kotlin есть какие-то более элегантные встроенные методы?
Ещё вопрос: как обрабатывать случай, когда строка может быть null? Например, когда данные приходят из внешнего API или базы данных. В Kotlin же есть нулл-безопасность, наверное, есть специальные функции?
Буду благодарен за примеры кода с пояснениями. Заранее спасибо!
<<Базовое преобразование: toLong()
Самый простой способ — использовать метод toLong(). Он выбрасывает NumberFormatException, если строка не является валидным целым числом:
val str = "123456789"
val number: Long = str.toLong()
println(number) // 123456789
Безопасное преобразование: toLongOrNull()
Kotlin предоставляет встроенную функцию toLongOrNull(), которая возвращает null вместо исключения, если преобразование невозможно. Это идеальное решение для пользовательского ввода:
val userInput = "abc123"
val number: Long? = userInput.toLongOrNull()
println(number) // null (без исключения)
// Пример с проверкой
val safeInput = "987654321"
val safeNumber = safeInput.toLongOrNull()
if (safeNumber != null) {
println("Успех: $safeNumber")
} else {
println("Ошибка: неверный формат")
}
Обработка null-строк
Если строка может быть null, используйте toLongOrNull() в паре с оператором безопасного вызова ?. или элвис-оператором ?::
val nullableStr: String? = null
val result = nullableStr?.toLongOrNull() ?: 0L
println(result) // 0
// Или с более сложной логикой
val fromApi: String? = "123"
val parsed = fromApi?.toLongOrNull()
when (parsed) {
null -> println("Не удалось распарсить")
else -> println("Значение: $parsed")
}
Использование toLong(radix) для систем счисления
Если нужно преобразовать строку из другой системы счисления (например, шестнадцатеричной), укажите основание:
val hexString = "1A3F"
val decimal = hexString.toLong(16) // основание 16
println(decimal) // 6719
// Безопасная версия с радиксом:
val safeHex = "XYZ".toLongOrNull(16)
println(safeHex) // null
Рекомендуемый паттерн для реального кода
В production-коде лучше всего комбинировать toLongOrNull() с обработкой через let или run:
fun parseUserInput(input: String?): Long {
return input?.toLongOrNull()?.let { validLong ->
println("Парсинг успешен: $validLong")
validLong
} ?: run {
println("Ввод некорректен, возвращаем значение по умолчанию")
0L
}
}
// Примеры использования
println(parseUserInput("123")) // Парсинг успешен: 123
println(parseUserInput("abc")) // Ввод некорректен, возвращаем значение по умолчанию
println(parseUserInput(null)) // Ввод некорректен, возвращаем значение по умолчанию
Сравнение с Java
- Java:
Long.parseLong(str)— исключение;Long.valueOf(str)— исключение;try-catchобязателен. - Kotlin:
str.toLongOrNull()— возвращает null; элегантно, безопасно, без исключений.
Используйте toLongOrNull() как основной инструмент. Он делает код чище, безопаснее и соответствует философии Kotlin — избегать исключений там, где это возможно.
Альтернативный подход: использование try-catch с функцией расширения
Хотя toLongOrNull() — предпочтительный вариант, иногда нужно сохранить информацию об ошибке. Например, для логирования или отображения пользователю конкретного сообщения. В таких случаях можно создать свою функцию-расширение:
fun String?.toLongSafe(): Result {
return try {
if (this == null) {
Result.failure(IllegalArgumentException("Строка равна null"))
} else {
Result.success(this.toLong())
}
} catch (e: NumberFormatException) {
Result.failure(e)
}
}
// Использование
val input = "abc"
val result = input.toLongSafe()
result.fold(
onSuccess = { value -> println("Успех: $value") },
onFailure = { error -> println("Ошибка: ${error.message}") }
)
Дополнительно: преобразование с учётом локали
Если строка содержит разделители тысяч (например, "1 000 000" или "1,000,000"), ни toLong(), ни toLongOrNull() не сработают. В этом случае нужно предварительно очистить строку:
fun String.removeSeparators(): String {
return this.replace(" ", "").replace(",", "").replace(".", "")
}
val formatted = "1 234 567 890"
val cleaned = formatted.removeSeparators()
val longValue = cleaned.toLongOrNull()
println(longValue) // 1234567890
Этот подход полезен при работе с пользовательским вводом из разных регионов, где разделители могут различаться.