Исключения
Классы исключений
Все классы исключений в Kotlin являются потомками класса Throwable. Каждое исключение имеет сообщение, стек вызовов и необязательную причину.
Чтобы выбросить объект исключения, используйте выражение throw:
fun main() {
//sampleStart
throw Exception("Hi There!")
//sampleEnd
}
Чтобы перехватить исключение, используйте выражение try:
try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}
Может быть ноль или более блоков catch. Блок finally может быть опущен. Однако должен быть присутствовать как минимум один блок catch или finally.
Try — это выражение
try — это выражение, т.е. оно может иметь возвращаемое значение:
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }
Возвращаемое значение выражения try — это либо последнее выражение в блоке try, либо последнее выражение в блоке catch (или блоках). Содержимое блока finally не влияет на результат выражения.
Проверяемые исключения
Kotlin не имеет проверяемых исключений. Есть много причин для этого, но мы приведем простой пример.
Следующее — это пример интерфейса JDK, реализованного классом StringBuilder:
Appendable append(CharSequence csq) throws IOException;
Что говорит эта сигнатура? Она говорит, что каждый раз, когда я добавляю строку к чему-то (будь то StringBuilder, какой-то журнал, консоль и т.д.), я должен перехватывать эти IOExceptions. Почему? Потому что может выполняться ввод-вывод (Writer также реализует Appendable )… Так что это приводит к такому коду повсюду:
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}
И это нехорошо, см. Effective Java, 3-е издание, пункт 77: Не игнорируйте исключения.
Брюс Эккель говорит о проверяемых исключениях:
Анализ небольших программ приводит к выводу, что требование спецификаций исключений может как повысить производительность разработчика, так и улучшить качество кода, но опыт работы с большими программными проектами показывает другой результат — снижение производительности и малое или нулевое повышение качества кода.
Другие цитаты такого рода:
- Проверяемые исключения Java — ошибка (Род Вальдхофф)
- Проблемы с проверяемыми исключениями (Андерс Хейлсберг)
Если вы хотите предупредить вызывающие стороны о возможных исключениях при вызове кода Kotlin из Java, Swift или Objective-C, вы можете использовать аннотацию @Throws. Подробнее об использовании этой аннотации читайте для Java и для Swift и Objective-C.
Тип Nothing
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' is known to be initialized at this point
Еще один случай, где вы можете столкнуться с этим типом, — это выведение типов. Нулевой вариант этого типа, Nothing?, имеет ровно одно возможное значение, которое является null. Если вы используете null для инициализации значения с выведенным типом и нет другой информации, которая может быть использована для определения более конкретного типа, компилятор выведет тип Nothing?:
val x = null // 'x' has type `Nothing?` val l = listOf(null) // 'l' has type `List<Nothing?>
Взаимодействие с Java
Дополнительную информацию о взаимодействии с Java, в том числе об исключениях, вы найдете в разделе Взаимодействие с Java.
© 2010–2020 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/reference/exceptions.html