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

November 22, 20223 хв читанняАрхів

Поговоримо про досить важливу річ у Kotlin – помилки. Ми вже стикалися з ними при розгляді деяких тем, тому розберімося з ними детальніше.

ℹ️ Визначення
Помилка – це стан деякої функціональності або програми, при якій неможлива робота цієї функціональності чи програми. Помилки поділяються на:

  1. Компіляційні (виявляються компілятором до запуску програми).
  2. Виконаційні (стаються під час роботи програми). Вони поділяються на Exception (виключення) та Error (помилки середи виконання).

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

Вони виникають, коли ви неправильно використовуєте ключові слова, або пишете те, чого не існує в мові Kotlin. Наприклад:

fun foo(bar) {
    println(bar)
}

Ми отримаємо помилку:

e: Main.kt: (1, 9): A type annotation is required on a value parameter

Тут (1, 9) означає, що помилка сталася на 1-й лінії та 9-му символі.

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

Компілятор також може показувати попередження. Код із ними працюватиме, але вони вказують на потенційні прогалини. Наприклад, якщо ви створили змінну, але не використовуєте її:

fun main() {
    val a = readln() // Попередження: Variable 'a' is never used
    println("Hello!")
}

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

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

структура throwable

Error#

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

Exception#

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

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

Ви можете створювати власні класи помилок, спадкуючи Exception:

class ExampleException(message: String) : Exception(message)
 
fun main() {
    throw ExampleException("Щось пішло не так")
}

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

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

Найочевидніший варіант — перевіряти вхідні дані за допомогою if або when.

val string = "abc"
if (string.length > 5) {
    println(string[5])
}

ℹ️ Нові функції для перевірки рядків

  • String.indices — діапазон індексів, що існують у рядку.
  • String.length — фізична кількість символів у рядку (якщо рядок порожній, length = 0).
  • String.lastIndex — індекс останнього символу (якщо рядок порожній, він дорівнює -1).

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

Якщо помилку важко передбачити перевіркою, використовуйте блок try-catch. Ви також можете використовувати його як вираз:

val number = try {
    readln().toInt()
} catch (e: NumberFormatException) {
    println("Неправильний формат числа!")
    0 // Значення за замовчуванням
}

Ви можете ловити декілька типів помилок одночасно:

try {
    // небезпечний код
} catch (e: NumberFormatException) {
    // обробка одного типу
} catch (e: Exception) {
    // обробка будь-якої іншої помилки
}

3. Null oriented design#

Kotlin пропонує безпечні альтернативи, що повертають null замість того, щоб "класти" програму. Такі функції зазвичай мають суфікс OrNull:

val number = readln().toIntOrNull() ?: 0
val firstChar = "abc".getOrNull(10) // Поверне null замість помилки

Висновок#

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

Пов'язані нотатки

Коментарі