type | layout | category | title | url |
---|---|---|---|---|
doc |
reference |
Syntax |
Исключения |
Все исключения в Kotlin являются наследниками класса Throwable
.
У каждого исключения есть сообщение, трассировка стека а также причина, по которой
это исключение вероятно было вызвано.
Для того, чтобы возбудить исключение явным образом, используйте оператор throw
throw MyException("Hi There!")
Оператор try позволяет перехватывать исключения
try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}
В коде может быть любое количество блоков catch (такие блоки могут и вовсе отсутствовать). Блоки finally могут быть опущены. Однако, должен быть использован как минимум один блок catch или finally.
Ключевое слово try является выражением, то есть оно может иметь возвращаемое значение.
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }
Возвращаемым значением будет либо последнее выражение в блоке try, либо последнее выражение в блоке catch (или блоках). Содержимое finally блока никак не повлияет на результат try-выражения.
В языке Kotlin нет проверяемых исключений. Для этого существует целый ряд причин, но мы рассмотрим простой пример.
Приведённый ниже фрагмент кода является примером простого интерфейса в JDK, который реализован в классе StringBulder
Appendable append(CharSequence csq) throws IOException;
О чём говорит нам сигнатура? О том, что каждый раз, когда я присоединяю строку к чему-то (к StringBuilder
, какому-нибудь логу, сообщению в консоль и т.п)
, мне необходимо отлавливать исключения типа IOExceptions
. Почему? Потому, что данная операция может вызывать IO (Input-Output: Ввод-Вывод) (Writer
также
реализует интерфейс Appendable
)...
Данный факт постоянно приводит к написанию подобного кода:
try {
log.append(message)
}
catch (IOException e) {
// Должно быть безопасно
}
И это плохо. См. Effective Java, Item 65: Don't ignore exceptions (не игнорируйте исключения).
Брюс Эккель как-то сказал в своей статье "Нужны ли в Java проверяемые исключения?"(Does Java need Checked Exceptions?):
Анализ небольших программ показал, что обязательная обработка исключений может повысить производительность разработчика и улучшить качество кода. Однако, изучение крупных проектов по разработке программного обеспечения позволяет сделать противоположный вывод: происходит понижение продуктивности и сравнительно небольшое улучшение кода (а иногда и без всякого улучшения).
Другие цитаты подобного рода:
- Java's checked exceptions were a mistake (Rod Waldhoff)
- The Trouble with Checked Exceptions (Anders Hejlsberg)
Вы можете использовать выражение throw
в качестве части элвис-выражения:
val s = person.name ?: throw IllegalArgumentException("Name required")
Типом выражения throw
является специалный тип под названием Nothing
.
У этого типа нет никаких значений, он используетя для того, чтобы обозначить те участки кода, которые могут быть не достигнуты никогда.
В своём коде вы можете использовать Nothing
для того, чтобы отметить функцию, чей результат никогда не будет возвращён:
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
При вызове такой функции компилятор будет в курсе, что исполнения кода далее не последует:
val s = person.name ?: fail("Name required")
println(s) // известно, что переменная 's' проинициализирована к этому моменту
См. раздел, посвещённый исключениям, в "Совместимости с Java" Java Interoperability section.