Kotlin для початківців: Структури даних — Помилки та Попередження

Архів
22 листопада 2022 р.3 хв читання
Kotlin для початківців
Поговоримо про досить важливу річ у Kotlin – помилки. Ми вже стикалися з ними при розгляді деяких тем, тому розберімося з ними детальніше.
ℹ️ Визначення
Помилка – це стан деякої функціональності або програми, при якій неможлива робота цієї функціональності чи програми. Помилки поділяються на:
  1. Компіляційні (виявляються компілятором до запуску програми).
  2. Виконаційні (стаються під час роботи програми). Вони поділяються на Exception (виключення) та Error (помилки середи виконання).

Компіляційні помилки

Вони виникають, коли ви неправильно використовуєте ключові слова, або пишете те, чого не існує в мові Kotlin. Наприклад:
kotlin
fun foo(bar) { println(bar) }
Ми отримаємо помилку:
text
e: Main.kt: (1, 9): A type annotation is required on a value parameter
Тут (1, 9) означає, що помилка сталася на 1-й лінії та 9-му символі.

Попередження (Warnings)

Компілятор також може показувати попередження. Код із ними працюватиме, але вони вказують на потенційні прогалини. Наприклад, якщо ви створили змінну, але не використовуєте її:
kotlin
fun main() { val a = readln() // Попередження: Variable 'a' is never used println("Hello!") }

Виконаційні помилки

Усі такі помилки будуються від однієї головної абстракції — класу Throwable, який має двох основних спадкоємців: Exception та Error.

Error

Це помилки, пов'язані із середовищем виконання (наприклад, JVM). Зазвичай ви не повинні їх обробляти у своєму коді. Приклад: OutOfMemoryError — коли програмі не вистачає пам'яті для завантаження величезного рядка чи об'єкта.

Exception

Це помилки, пов'язані безпосередньо з логікою вашого коду. Їх можна (і часто треба) передбачати та обробляти. Приклади: NumberFormatException (коли текст не є числом) або StringIndexOutOfBoundsException (спроба отримати символ за індексом, якого не існує).

Власні помилки

Ви можете створювати власні класи помилок, спадкуючи Exception:
kotlin
class ExampleException(message: String) : Exception(message) fun main() { throw ExampleException("Щось пішло не так") }

Запобігання помилкам

1. Перевірка даних

Найочевидніший варіант — перевіряти вхідні дані за допомогою if або when.
kotlin
val string = "abc" if (string.length > 5) { println(string[5]) }
ℹ️ Нові функції для перевірки рядків
  • String.indices — діапазон індексів, що існують у рядку.
  • String.length — фізична кількість символів у рядку (якщо рядок порожній, length = 0).
  • String.lastIndex — індекс останнього символу (якщо рядок порожній, він дорівнює -1).

2. Оператор try-catch

Якщо помилку важко передбачити перевіркою, використовуйте блок try-catch. Ви також можете використовувати його як вираз:
kotlin
val number = try { readln().toInt() } catch (e: NumberFormatException) { println("Неправильний формат числа!") 0 // Значення за замовчуванням }
Ви можете ловити декілька типів помилок одночасно:
kotlin
try { // небезпечний код } catch (e: NumberFormatException) { // обробка одного типу } catch (e: Exception) { // обробка будь-якої іншої помилки }

3. Null oriented design

Kotlin пропонує безпечні альтернативи, що повертають null замість того, щоб "класти" програму. Такі функції зазвичай мають суфікс OrNull:
kotlin
val number = readln().toIntOrNull() ?: 0 val firstChar = "abc".getOrNull(10) // Поверне null замість помилки

Висновок

  • Помилки бувають компіляційні та виконаційні.
  • Throwable — корінь усіх помилок, що поділяється на Exception (логіка) та Error (система).
  • Використовуйте перевірки та підхід OrNull всюди, де це можливо, а try-catch — лише як останній засіб.