Идиоматическая обработка исключений в kotlin

При обработке исключений мне понадобилась эта удобная маленькая функция:

inline fun exec(lambda: () -> Any): Boolean = try { lambda() ; true } catch(e:Exception) { false }

Существуют ли такие функции в Котлине? Существуют ли идиоматические альтернативы сложному синтаксису try-catch-finnaly?

Из любопытства: каков ваш вариант использования для этого? Лично я предпочитаю исключения функции, которая просто возвращает логическое значение successful, потому что разные исключения могут быть выброшены в разных сценариях ошибок, что позволяет по-разному обрабатывать ошибки.

vatbub 11.12.2020 16:25

Это плохая идея по нескольким причинам. Если возникло исключение, как узнать, что пошло не так? Ваша функция полностью проглатывает исключение, даже не регистрируя его. Таким образом, невозможно узнать, какое исключение было сгенерировано, где оно было сгенерировано или какое сообщение оно содержало. (И если вы предполагаете, что только одна вещь может пойти не так, вы, скорее всего, что-то упускаете…)  Подобная функция делает невозможным отладку проблем с кодом или обработку нескольких типов ошибок…

gidds 11.12.2020 18:20

… Он также требует (но не принуждает) прямого вызывающего объекта проверять возвращаемое значение и либо обрабатывать его тут же, либо возвращать его вызывающему объекту и так далее. Наконец, он требует, чтобы лямбда возвращала ненулевые значения, а затем игнорирует его.

gidds 11.12.2020 18:20

Существуют определенные ситуации при взаимодействии с кодом Java, когда может иметь смысл обернуть код, вызывающий исключение, чем-то, что просто возвращает null в случае сбоя. Но обычно вы хотите обернуть только определенные исключения, которые вы ожидаете, такие как IllegalArgumentException и NumberFormatException, как способ проглотить исключения, которые вам не нужно регистрировать, потому что они указывают на то, что вы ожидали, может произойти, например, если вы передадите user ввод для некоторой проверки.

Tenfour04 11.12.2020 19:49

@vatbub Это было что-то вроде этого kotlin val isAudio = isAudioFile(source) && exec { m.setDataSource(source.canonicalPath) } setDataSource выбрасывал бы, если бы была проблема с доступностью данных

Pylvain 11.12.2020 20:18

Для такого сценария использования вы не найдете функции в стандартной библиотеке — по вышеуказанным причинам. Однако в вашем случае я предлагаю вам переименовать функцию. exec на самом деле не представляет цель функции, которая заключается в проверке того, выдает ли код исключение. Я бы лучше назвал его throws

vatbub 11.12.2020 20:24

@vatbub Я заменил код на runCatching{}.isSuccess. Это меня устраивает

Pylvain 11.12.2020 20:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
886
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать runCatching, а затем использовать .isSuccess для результата, чтобы получить логическое значение успеха.

runCatching {
    // your code
}.isSuccess

Если вашему коду нужен результат, и вы хотите вернуть null в случае ошибки (что является идиоматичным Kotlin), вы можете сделать

val foo: Foo? = runCatching {
    // your code that produces a Foo
}.getOrNull()
runCatching может быть немного опасным. Если бы приведенный выше пример кода относился к OutOfMemoryError (или любому другому java.lang.Error, который вы, вероятно, не должны перехватывать), он был бы проглочен. Попробуйте вместо этого использовать try/catch.
Tony 29.03.2023 22:05

Другие вопросы по теме