Освоюємо Kotlin/Винятки
Винятки (англ. Exceptions) — це аварійні ситуації, які виникають під час виконання програми. Прикладом може слугувати ділення на нуль, звертання до неіснуючого елементу масиву. Такі ситуації прийнято зазделегідь передбачати. Часто компілятор сам вам підкаже, що можлива виняткова ситуація. Для обробки винятків в Kotlin існує конструкція try-catch.
Приклад Exception
[ред.]Маємо такий код:
ArithmeticException
fun main() {
val result = 10 / 0 // це викине ArithmeticException
println("Result: $result")
}
|
Виконання цієї програми завершиться аварійно. Вам у консоль видасть наступний виняток:
Результат:
Exception in thread "main" java.lang.ArithmeticException: / by zero at MainKt.main(Main.kt:2) at MainKt.main(Main.kt) |
Тут бачимо назву винятку "java.lang.ArithmeticException / by zero", в наступному рядочку пише номер рядка програми(у нас 2) в якому виник виняток.
Інший частий випадок це ArrayIndexOutOfBoundsException. Це виняток, який виникає при зверненні до масиву за неіснуючим індексом:
ArrayIndexOutOfBoundsException:
fun main(){
val array = arrayOf(5,3,6,8)
println(array[8]) //звернення за межі існуючих індексів масиву
}
|
Результат:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 8 out of bounds for length 4 at TestSetKt.main(TestSet.kt:3) at TestSetKt.main(TestSet.kt) |
Для того, щоб програма змогла працювати і не припиняла роботу слід використати конструкцію try-catch.
try-catch
[ред.]Конструкція try-catch має наступний загальний вигляд:
try {
//код, що може спричинити проблему
} catch (e: ArithmeticException) {
//дії при виникненні Exception
} finally {
//дії, що виконаються в будь-якому разі
}
Блоку finally може не бути при умові наявності catch, також може не бути catch при наявності finally.
Використаємо try-catch для обробки ділення на нуль:
fun main() {
try {
// код, що може викинути Exception
val result = 10 / 0 //ArithmeticException
println("Result: $result")
} catch (e: ArithmeticException) {
// код для обробки ArithmeticException
println("Помилка ділення на нуль!")
println("Неждана помилка виникла: ${e.message}")
e.printStackTrace() // Надрукувати відбиток стеку
}
}
Результат:
Помилка ділення на нуль! Неждана помилка виникла: / by zero java.lang.ArithmeticException: / by zero at MainKt.main(Main.kt:4) at MainKt.main(Main.kt) |
Можемо добавити finally, щоб здійснити якісь дії після catch:
try {
// код, що може викинути Exception
val result = 10 / 0 //ArithmeticException
println("Result: $result")
} catch (e: ArithmeticException) {
// код для обробки ArithmeticException
println("Помилка ділення на нуль!")
println("Неждана помилка виникла: ${e.message}")
e.printStackTrace() // Надрукувати відбиток стеку
}finally{
println("Виконання дій в кінці конструкції try-catch")
}
Блоків catch може бути кілька. Так один може ловити ArithmeticException, а інший всі інші винятки:
try {
// код, що може викинути Exception
val result = 10 / 0 //ArithmeticException
println("Result: $result")
} catch (e: ArithmeticException) {
// код для обробки ArithmeticException
println("Помилка ділення на нуль!")
println("Виникла неждана помилка: ${e.message}")
e.printStackTrace() // Надрукувати відбиток стеку
} catch (e: Exception) {
// ловимо всі інші винятки
println("Виникла неждана помилка: ${e.message}")
}finally{
println("Виконання дій в кінці конструкції try-catch")
}
В даному випадку виконається лише перший блок catch, оскільки він зловив виняток. Якщо б в коді виник не ArithmeticException, а інший виняток, то спрацював би блок із другим catch.
Можна написати багато блоків catch, кожен з яких буде ловити свій виняток.
Викидання винятків
[ред.]Ви можете самі викинути виняток в коді програми:
throw IllegalArgumentException()
Цей виняток згодом може бути оброблений вами, або іншим програмістом.
Якщо ви хочете вказати більш детальну інформацію про виняток, то необхідно викинути його з параметрами message (повідомлення) та cause (причина):
val userInput=-2
val cause = IllegalStateException("Original cause: illegal state")
// Викидає IllegalArgumentException якщо userInput від'ємний
// Додатково, вказуємо причину IllegalStateException
if (userInput < 0) {
throw IllegalArgumentException("Input must be non-negative", cause)
}
Детальніше про витятки читайте тут
Джерела
[ред.](необхідно дописати про функції require(), check() та error())