JavaRush /Курси /Kotlin SELF /Конвертація між типами даних

Конвертація між типами даних

Kotlin SELF
Рівень 2 , Лекція 3
Відкрита

1. Навіщо потрібна конвертація типів?

Kotlin — це строго (статично) типізована мова. Якщо у компʼютера є «коробочка» для числа, то спроба покласти туди текст — приблизно те саме, що й спроба вставити виделку в USB-розʼєм. Компілятор такого не дозволить.

Утім у реальному житті ми часто працюємо з різними типами даних одночасно. Наприклад, у вас є рядок, що містить число. Саме тут і потрібна конвертація (або перетворення) типів.

Розгляньмо приклад. Припустімо, ви хочете зберігати кількість користувачів:

val a: Int = 1
val b: Int = "2"
val c: Int = "три"

Компілятор тут одразу скаже: «Я не вмію автоматично перетворювати рядок на число. Потрібно явно перетворити рядок на число».

У Kotlin є кілька способів конвертації. Кожен має свої плюси й мінуси, а також типові підводні камені.

2. Перетворюємо Int на String

У роботі часто потрібно отримати рядкове подання числа: наприклад, щоб вивести його на екран, зберегти у файл, передати мережею, обʼєднати з текстом тощо. У Kotlin для цього є відразу кілька способів — зручних у різних ситуаціях.

Функція toString()

Це основний і найпоширеніший спосіб:

val number = 42
val str = number.toString()  // str == "42"

toString() перетворює значення на рядок, що відповідає типу цього значення.

Конкатенація з порожнім рядком

Старий, але робочий спосіб:

val number = 42
val str = "" + number

Такий підхід зручний у простих випадках, але для людини, яка читає код, він менш очевидний.

3. Неявне перетворення на рядок

Як уже згадували вище, у Kotlin можна перетворити на String будь-що: змінні, обʼєкти та вирази.

Ба більше, це відбувається автоматично, коли ми додаємо значення типу String до значення будь-якого іншого типу. Наприклад:

val a = 5
val name = "Аня" + a            // name містить рядок Аня5
val a = 5
val city = a + "New York" + a   // city містить рядок 5New York5
val number = 10
val code = "Yo"
val message = "Привіт! " + number + code // message містить рядок Привіт! 10Yo

У всіх трьох прикладах ми додавали змінні типів Int і String, а в результаті завжди отримували String.

Важливо! Арифметичні операції з типом String виконувати не можна — навіть якщо рядок повністю складається з цифр.

Приклади:

val a = 5
val name = "1" + a              // name містить рядок 15
val a = 5
val city = a + "9" + a          // city містить рядок 595
val number = 10
val code = "10"
val message = "" + number + code // message містить рядок 1010

Операція додавання виконується зліва направо, тож результат може бути дещо несподіваним. Наприклад:

val a = 5
val name = a + a + "1" + a      // name містить рядок 1015

Порядок виконання: ((a + a) + "1") + a

4. Перетворення рядка на число: toInt()

Щоб перетворити число на рядок у Kotlin, достатньо додати його до порожнього рядка:

val str = "" + число

А що робити, якщо потрібно перетворити рядок на число? Перетворити на число можна не будь-який рядок. Але якщо рядок складається лише з цифр, це можливо. Для цього в Kotlin є спеціальна функція.

Виклик виглядає так:

val x: Int = рядок.toInt()
Перетворення рядка на число через toInt()

Де val x: Int — це оголошення цілочисельної змінної x, а рядок — це число, задане у вигляді рядка (тобто рядок, що складається з цифр).

Приклади:

val str = "123"
val number1 = str.toInt()               // number1 містить число 123

val number2 = "321".toInt()             // number2 містить число 321

val number3 = ("321" + 0).toInt()       // number3 містить число 3210

val number4: Int = "321"                // Не скомпілюється: змінна типу Int, а значення типу String

Для відʼємних значень це теж працює: функція toInt() коректно обробляє знак -.

5. toIntOrNull(): безпечне перетворення на число

Коли рядок приходить із зовнішнього світу (з файлу або від користувача), завжди є ризик, що це не число. Саме тут і стане в пригоді безпечніший метод: toIntOrNull().

Він працює так: якщо рядок справді містить ціле число — поверне Int. Якщо ні — поверне null. Це принципово інша поведінка порівняно з toInt(): замість помилки під час запуску й падіння програми ми отримаємо спеціальне значення — null.

null — це спеціальне значення, яке означає «значення немає». Тобто null — це не 0, не порожній рядок і не «помилка у вигляді тексту». Це саме «відсутність результату».

Розширюємо тип Int: Int?

Тип Int зберігає лише коректні цілі числа. Він не може зберігати рядки, дробові числа, а також значення null. Тому в Kotlin є розширений варіант типу IntInt?. Він може зберігати всі значення типу Int і значення null (коли значення немає).

Це настільки поширена ситуація, що в Kotlin її зробили частиною мови: до будь-якого типу можна додати знак питання й отримати «розширений тип», який може зберігати ще й null.

Якщо звичайний Int завжди містить число, то Int? читається як «або Int, або null». Знак питання — це буквально позначка «може бути відсутнім».

Метод toIntOrNull() повертає Int?, тому що він може як успішно розібрати число, так і не впоратися з перетворенням.

Мініприклад: успішний і неуспішний розбір

Корисно побачити, що станеться в обох випадках, і не намагатися «вгадувати» результат.

fun main() {
    val ok: Int? = "15".toIntOrNull()
    val bad: Int? = "15a".toIntOrNull()

    println(ok)   // 15
    println(bad)  // null
}

6. Шпаргалка та практика перетворень

Коли способів стає кілька, мозок просить «шпаргалку». І це нормально: ви не зобовʼязані тримати все в голові. Важливіше вміти швидко відновлювати сенс і добирати правильний інструмент.

Таблиця-памʼятка: toString() vs toInt() vs toIntOrNull()

Метод Звідки → куди Коли використовувати Що буде, якщо рядок не число
toString()
Int → String
потрібно вивести / обʼєднати з текстом не застосовно (ми перетворюємо число)
toInt()
String → Int
ви впевнені, що рядок коректний помилка під час запуску (виняток)
toIntOrNull()
String → Int?
рядок може бути «неохайним» поверне null

Чому Kotlin змушує робити перетворення явними

Коли люди вперше стикаються з явними перетвореннями, часто виникає запитання: «Чому мова сама не здогадається, що "123" — це число?» Але мова якраз не хоче вгадувати.

Уявіть: ви написали "007". Це число сім? Чи це код відділу? Або ж рядок, у якому важливі провідні нулі? Якби мова автоматично перетворювала рядки на числа, вона регулярно помилялася б. Kotlin обирає передбачуваність: якщо вам потрібне число — викличте toInt() або toIntOrNull() і свідомо ухваліть це рішення.

Це, по суті, «доросла» позиція мови. Kotlin ніби каже: «Я не телепат. Я компілятор».

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ