В чём разница между исключениями в Java и Kotlin?
Разница между исключениями в Java и Kotlin касается в основном обязательности обработки, синтаксиса, а также подхода к исключениям как части языка. Kotlin унаследовал модель исключений Java, но упростил и упростил её использование.
🔹 1. Проверяемые и непроверяемые исключения
В Java:
Java делит исключения на два типа:
-
Проверяемые (checked) — наследники Exception, но не RuntimeException.
-
Компилятор требует либо обработать их (try-catch), либо объявить в throws.
-
Пример: IOException, SQLException.
-
-
Непроверяемые (unchecked) — наследники RuntimeException или Error.
-
Не требуют явной обработки.
-
Пример: NullPointerException, IllegalArgumentException.
-
public void readFile() throws IOException {
FileReader reader = new FileReader("file.txt"); // must handle IOException
}
В Kotlin:
Нет checked-исключений вообще.
Все исключения в Kotlin — непроверяемые (как RuntimeException в Java).
fun readFile() {
val reader = FileReader("file.txt") // можно не оборачивать в try-catch
}
→ Компилятор не требует try-catch или throws.
🔸 2. Синтаксис обработки
Синтаксис try-catch-finally очень похож, но в Kotlin он более выразителен, потому что try — это выражение, а не просто блок:
Java:
try {
int x = 1 / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
System.out.println("Done");
}
Kotlin:
val result = try {
1 / 0
} catch (e: ArithmeticException) {
0
} finally {
println("Done")
}
→ try может возвращать значение, как if или when.
🔹 3. Нет throws в сигнатуре
В Java вы должны явно указывать в сигнатуре, какие checked-исключения может выбросить метод:
public void risky() throws IOException
В Kotlin нет ключевого слова throws в сигнатурах по умолчанию, и компилятор не проверяет это. Хотя вы можете использовать аннотацию @Throws для совместимости с Java:
@Throws(IOException::class)
fun risky() { ... }
🔸 4. Исключения из Java в Kotlin
Kotlin может вызывать Java-код, выбрасывающий checked-исключения, без обязательного try-catch.
val reader = FileReader("file.txt") // IOException возможен, но обработка не обязательна
🔹 5. Создание и выбрасывание исключений
И в Java, и в Kotlin для генерации исключения используется throw, но в Kotlin throw — это выражение типа Nothing, что позволяет использовать его, например, в выражениях:
val name = input ?: throw IllegalArgumentException("Name required")
→ Это невозможно в Java так элегантно.
🔸 6. Пользовательские исключения
Создание кастомных исключений почти одинаково:
Java:
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
Kotlin:
class MyException(message: String) : Exception(message)
🧠 Сравнение по ключевым аспектам
Аспект | Java | Kotlin |
---|---|---|
Checked-исключения | ✅ Да (обязательны к обработке) | ❌ Нет (все исключения — unchecked) |
--- | --- | --- |
throws в сигнатуре | ✅ Обязателен для checked | ❌ Не используется (кроме @Throws для Java) |
--- | --- | --- |
try как выражение | ❌ Нет | ✅ Да |
--- | --- | --- |
Тип throw | void | Nothing (можно использовать в выражениях) |
--- | --- | --- |
Компилятор требует catch? | ✅ Для checked | ❌ Нет |
--- | --- | --- |
📦 Вывод
-
Kotlin упрощает работу с исключениями, устранив checked-исключения и сделав try выражением.
-
В Kotlin вы обрабатываете ошибки по желанию, а не по требованию компилятора.
-
Это повышает гибкость и читаемость, но требует от разработчика ответственности за контроль над ошибками.