type | layout | category | title | url |
---|---|---|---|---|
doc |
reference |
Syntax |
Исключения |
Все исключения в Kotlin являются наследниками класса Throwable
.
У каждого исключения есть сообщение, трассировка стека и (опционально) причина, по которой
это исключение вероятно было вызвано.
Для того чтобы возбудить исключение явным образом, используйте оператор throw
.
throw Exception("Hi There!")
Чтобы перехватить исключение, используйте выражение try
...catch
.
try {
// some code
} catch (e: SomeException) {
// handler
} finally {
// optional finally block
}
В коде может быть любое количество блоков catch
(такие блоки могут и вовсе отсутствовать). Блоки finally
могут быть опущены. Однако, должен быть использован как минимум один блок catch
или finally
.
try
является выражением, что означает, что оно может иметь возвращаемое значение.
val a: Int? = try { input.toInt() } catch (e: NumberFormatException) { null }
Возвращаемым значением будет либо последнее выражение в блоке try
, либо последнее выражение
в блоке catch
(или блоках). Содержимое finally
блока никак не повлияет на результат try
-выражения.
В Kotlin нет проверяемых исключений. Для этого существует целый ряд причин, но мы рассмотрим простой пример, который иллюстрирует причину этого.
Приведённый ниже фрагмент кода является примером простого интерфейса в JDK, который реализован в классе StringBuilder
.
Appendable append(CharSequence csq) throws IOException;
Сигнатура говорит, что каждый раз, когда я присоединяю строку к чему-то (к StringBuilder
, какому-нибудь логу, сообщению в консоль и т.п),
мне необходимо отлавливать исключения типа IOExceptions
. Почему? Потому, что данная операция может вызывать IO (Input-Output: Ввод-Вывод) (Writer
также
реализует интерфейс Appendable
).
Данный факт постоянно приводит к написанию подобного кода:
try {
log.append(message)
} catch (IOException e) {
// Должно быть безопасно
}
И это плохо. См. Effective Java, Item 77: Don't ignore exceptions (не игнорируйте исключения).
Брюс Эккель как-то сказал о проверяемых исключения:
Анализ небольших программ показал, что обязательная обработка исключений может повысить производительность разработчика и улучшить качество кода. Однако, изучение крупных проектов по разработке программного обеспечения позволяет сделать противоположный вывод: происходит понижение продуктивности и сравнительно небольшое улучшение кода (а иногда и без всякого улучшения).
Вот несколько других рассуждений по этому поводу:
- Java's checked exceptions were a mistake (Rod Waldhoff)
- The Trouble with Checked Exceptions (Anders Hejlsberg)
Если вы хотите предупредить вызывающие объекты о возможных исключениях при вызове Kotlin кода из Java, Swift или Objective-C,
вы можете использовать аннотацию @Throws
. Узнайте больше об использовании этой аннотации для Java,
а также для Swift и Objective-C.
throw
в Kotlin является выражением, поэтому есть возможность использовать его, например, в качестве части Elvis-выражения:
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' проинициализирована к этому моменту
Вы также можете столкнуться с этим типом при работе с выводом типов.
Nullable-вариант этого типа Nothing?
имеет ровно одно возможное значение - null
.
Если вы используете null
для инициализации значения предполагаемого типа, и нет никакой другой информации,
которую можно использовать для определения более конкретного типа, компилятор определит тип Nothing?
.
val x = null // у 'x' тип `Nothing?`
val l = listOf(null) // у 'l' тип `List<Nothing?>
См. раздел, посвящённый исключениям, Страница совместимости Java для получения информации о совместимости с Java.