При обработке исключений мне понадобилась эта удобная маленькая функция:
inline fun exec(lambda: () -> Any): Boolean = try { lambda() ; true } catch(e:Exception) { false }
Существуют ли такие функции в Котлине? Существуют ли идиоматические альтернативы сложному синтаксису try-catch-finnaly?
Это плохая идея по нескольким причинам. Если возникло исключение, как узнать, что пошло не так? Ваша функция полностью проглатывает исключение, даже не регистрируя его. Таким образом, невозможно узнать, какое исключение было сгенерировано, где оно было сгенерировано или какое сообщение оно содержало. (И если вы предполагаете, что только одна вещь может пойти не так, вы, скорее всего, что-то упускаете…) Подобная функция делает невозможным отладку проблем с кодом или обработку нескольких типов ошибок…
… Он также требует (но не принуждает) прямого вызывающего объекта проверять возвращаемое значение и либо обрабатывать его тут же, либо возвращать его вызывающему объекту и так далее. Наконец, он требует, чтобы лямбда возвращала ненулевые значения, а затем игнорирует его.
Существуют определенные ситуации при взаимодействии с кодом Java, когда может иметь смысл обернуть код, вызывающий исключение, чем-то, что просто возвращает null в случае сбоя. Но обычно вы хотите обернуть только определенные исключения, которые вы ожидаете, такие как IllegalArgumentException
и NumberFormatException
, как способ проглотить исключения, которые вам не нужно регистрировать, потому что они указывают на то, что вы ожидали, может произойти, например, если вы передадите user ввод для некоторой проверки.
@vatbub Это было что-то вроде этого kotlin val isAudio = isAudioFile(source) && exec { m.setDataSource(source.canonicalPath) }
setDataSource выбрасывал бы, если бы была проблема с доступностью данных
Для такого сценария использования вы не найдете функции в стандартной библиотеке — по вышеуказанным причинам. Однако в вашем случае я предлагаю вам переименовать функцию. exec
на самом деле не представляет цель функции, которая заключается в проверке того, выдает ли код исключение. Я бы лучше назвал его throws
@vatbub Я заменил код на runCatching{}.isSuccess. Это меня устраивает
Вы можете использовать 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.
Из любопытства: каков ваш вариант использования для этого? Лично я предпочитаю исключения функции, которая просто возвращает логическое значение
successful
, потому что разные исключения могут быть выброшены в разных сценариях ошибок, что позволяет по-разному обрабатывать ошибки.