Разбор поведения кода с CoroutineExceptionHandler

Обработчик во вложенном launch не перехватит ошибку: дочерняя корутина передаст её родителю. Ошибка отменит обычный Job и будет обработана как неперехваченная.

Короткий ответ

Что ответить на собеседовании

Обработчик во вложенном launch не перехватит ошибку: дочерняя корутина передаст её родителю. Ошибка отменит обычный Job и будет обработана как неперехваченная.

Подробный разбор

Ответ с пояснениями

Условие

Определить, какое действие произойдёт при запуске следующего фрагмента кода.

fun main() {

    val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, exception ->
        println("Handle $exception in CoroutineExceptionHandler")
    }

    val topLevelScope = CoroutineScope(Job())

    topLevelScope.launch {
        launch(coroutineExceptionHandler) {
            throw RuntimeException("RuntimeException in nested coroutine")
        }
    }
}

Ответ

Обработчик во вложенном launch не перехватит ошибку: дочерняя корутина передаст её родителю. Ошибка отменит обычный Job и будет обработана как неперехваченная.

Вложенный launch — не корневая корутина, и установленный на нём CoroutineExceptionHandler не заменяет распространение ошибки к родителю. Внешний launch обработчика не имеет. Для такой структуры handler нужно передать внешнему launch либо включить в контекст исходного scope.

Handler не восстанавливает упавшую корутину; ожидаемую ошибку обрабатывают try/catch внутри выполняемой операции. Отдельная тонкость примера: main сразу заканчивается, не ожидая launch, поэтому увидеть какой-либо вывод или stack trace до завершения процесса не гарантируется.

Источник: kotlinlang.org.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее