Почему вы должны заключать проверенные исключения в лямбда-выражения в непроверенное исключение? - PullRequest
4 голосов
/ 20 января 2020

Я являюсь Java разработчиком около двух лет, и если есть что-то, что мне действительно нравится в этом языке, это потоковый API. Это делает мой код намного более беглым, понятным и читаемым.

Единственное, что меня беспокоит, так это то, как исключения должны обрабатываться при работе с лямбда-кодами. Я прочитал несколько статей на эту тему и видел несколько вопросов о StackOverflow. Общее согласие заключается в том, что вам нужно обернуть вызов метода, чтобы перехватить проверенное исключение и перебросить непроверенное исключение . (вот так: https://www.oreilly.com/ideas/handling-checked-exceptions-in-java-streams)

Но я еще не прочитал или не понял, почему это хорошая идея. Преимущество проверенных исключений состоит в том, что вызывающий абонент знает, чего ожидать. Меня учили, что всякий раз, когда вы хотите обеспечить соблюдение бизнес-правил, проверенные исключения - это путь к go. Непроверенные исключения должны быть зарезервированы для тех случаев, когда приложение не может восстановиться после исключения. Так почему же они заставили нас использовать непроверенные исключения при работе с потоками? На первый взгляд это кажется большим недостатком, верно?

В настоящее время я пишу SOAP веб-сервис, и большим преимуществом является то, что все возможные ошибки бизнеса, которые могут быть обнаружены, хорошо определены. Клиент может соответственно реагировать на возникающие исключения. Создание исключения во время выполнения может привести к тому, что клиент получит исключение SOAPFaultException, не зная, что, черт возьми, пошло не так или как его обработать.

Я мог бы использовать глобальный обработчик исключений и перехватить все возможные RTE (если я не забыть некоторые), а затем еще раз сбросить их как одно из проверенных исключений, определенных в XSD / WSDL. Но мне довольно трудно убедить моих старших коллег в преимуществах функционального программирования и сказать им, чтобы они свернули свои проверенные исключения в непроверенные исключения, но только превращение их в проверенные исключения определенно не поможет моему положению.

Так почему же перехватывать проверенные исключения в лямбдах и заключать их в непроверенные исключения считается хорошим способом сделать это? Существует очень немного других сценариев, в которых мы действительно поймаем проверенное исключение и сгенерируем непроверенное исключение. Так почему это считается хорошим вариантом при работе с лямбда? Действительно ли это потому, что это единственный возможный способ сделать это (безопасно для нескольких грязных обходных путей, таких как @SneakyThrows Ломбока), учитывая ограничения языка? И как ты справляешься со всеми этими неуправляемыми ракетами?

1 Ответ

1 голос
/ 21 января 2020

Зачем вам заключать проверенные исключения в лямбда-выражения в непроверенное исключение?

Краткий ответ: потому что вы должны это сделать. (В значительной степени.)

Так почему же они заставили нас использовать непроверенные исключения при работе с потоками? На первый взгляд это кажется большим недостатком, верно?

Не вдаваясь в историю и споры о том, были ли проверенные исключения ошибочными или нет ...

Обработка исключений в потоках и лямбдах на самом деле является прямым следствием общего дизайна Java исключений и обработки исключений. Последнее не может быть изменено: это было бы слишком разрушительным для существующей Java клиентской базы Oracle. Поэтому мы застряли с этим в обозримом будущем.

Действительно ли это потому, что это единственный возможный способ сделать это (безопасно для нескольких грязных обходных путей, таких как @SneakyThrows Ломбока), учитывая ограничения языка?

Да, это единственный способ. Хорошо это или нет.

И как вы справляетесь со всеми этими неуправляемыми ракетами?

Один из способов - просто позволить неконтролируемому (или подлому) проверено) исключение распространяю. В большинстве случаев приложение или поток обработают sh, и вы можете использовать трассировку стека в файле журнала, чтобы найти / устранить причину root. Это предполагает, что исходное проверенное исключение не является «ожидаемым» и поэтому не подлежит восстановлению.

Если вы пытаетесь восстановить приложение из проверенного исключения:

  • Для исключенного исключения вы можете поймать RuntimeException, а затем использовать ex.getClass() и ex.getCause(), чтобы решить, что делать.

  • Для скрытого проверенного исключения вы можете поймать Exception и используйте instanceof, чтобы отличить (ожидаемые) скрытые проверенные исключения от непроверенных.

...