Чтобы избежать всех стандартных ответов, на которые я мог бы гуглить, я приведу пример, который вы все можете атаковать по своему желанию.
C # и Java (и слишком много других) имеют множество типов поведения «переполнения», которое мне совсем не нравится (например, type.MaxValue + type.SmallestValue == type.MinValue
например:) int.MaxValue + 1 == int.MinValue
.
Но, увидев мою порочную натуру, я добавлю немного оскорблений к этой травме, расширив это поведение, скажем до переопределенного DateTime
типа. (Я знаю, что DateTime
это запечатано в .NET, но ради этого примера я использую псевдоязык, точно такой же, как C #, за исключением того факта, что DateTime не запечатан).
Переопределенный Add
метод:
/// <summary>
/// Increments this date with a timespan, but loops when
/// the maximum value for datetime is exceeded.
/// </summary>
/// <param name="ts">The timespan to (try to) add</param>
/// <returns>The Date, incremented with the given timespan.
/// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and
/// continue from DateTime.MinValue.
/// </returns>
public DateTime override Add(TimeSpan ts)
{
try
{
return base.Add(ts);
}
catch (ArgumentOutOfRangeException nb)
{
// calculate how much the MaxValue is exceeded
// regular program flow
TimeSpan saldo = ts - (base.MaxValue - this);
return DateTime.MinValue.Add(saldo)
}
catch(Exception anyOther)
{
// 'real' exception handling.
}
}
Конечно, если бы это можно было решить так же просто, но факт остается фактом: я просто не понимаю, почему вы не можете использовать исключения (логически, то есть я вижу, что, когда производительность - это проблема, в некоторых случаях следует избегать исключений). ).
Я думаю, что во многих случаях они более понятны, чем if-структуры, и не нарушают контракт, заключаемый методом.
ИМХО, реакция «Никогда не используйте их для регулярного выполнения программы», как кажется, у всех, похоже, не так уж недооценена, как может оправдать сила этой реакции.
Или я ошибаюсь?
Я читал другие посты, посвященные разного рода особым случаям, но я считаю, что в этом нет ничего плохого, если вы оба:
- Очистить
- Уважайте контракт вашего метода
Стреляй в меня.
if
утверждение. Вы найдете это очень сложно. Другими словами: сама ваша предпосылка ошибочна, и выводы, которые вы из нее делаете, ошибочны.Ответы:
Вы когда-нибудь пытались отладить программу, генерирующую пять исключений в секунду в ходе обычной работы?
У меня есть.
Программа была довольно сложной (это был сервер распределенных вычислений), и небольшая модификация на одной стороне программы могла легко сломать что-то в совершенно другом месте.
Хотелось бы просто запустить программу и ждать появления исключений, но при запуске в обычном режиме работы было около 200 исключений
Моя точка зрения: если вы используете исключения для нормальных ситуаций, как вы находите необычные (то есть исключения ) ситуации?
Конечно, есть и другие веские причины не использовать исключения слишком часто, особенно в отношении производительности.
источник
Исключением являются в основном нелокальные
goto
утверждения со всеми последствиями последнего. Использование исключений для управления потоком нарушает принцип наименьшего удивления , затрудняя чтение программ (помните, что программы сначала пишутся для программистов).Более того, этого не ожидают производители компиляторов. Они ожидают, что исключения будут создаваться редко, и они обычно позволяют
throw
коду быть весьма неэффективным. Создание исключений - одна из самых дорогих операций в .NET.Однако некоторые языки (особенно Python) используют исключения в качестве конструкций управления потоком. Например, итераторы выдают
StopIteration
исключение, если больше нет элементов. Даже стандартные языковые конструкции (такие какfor
) полагаются на это.источник
goto
, конечно, исключения правильно взаимодействуют с вашим стеком вызовов и с лексической областью видимости и не оставляют стек или области в беспорядке.Мое правило:
Проблема, которую я вижу с исключениями, связана с чисто синтаксической точки зрения (я уверен, что издержки производительности минимальны). Я не люблю пробные блоки повсюду.
Возьмите этот пример:
.. Другой пример может быть, когда вам нужно назначить что-то для дескриптора, используя фабрику, и эта фабрика может выдать исключение:
Итак, лично я думаю, что вы должны оставить исключения для редких состояний ошибок (нехватка памяти и т. Д.) И использовать возвращаемые значения (классы значений, структуры или перечисления) вместо этого для проверки ошибок.
Надеюсь, я правильно понял ваш вопрос :)
источник
Первая реакция на множество ответов:
Конечно! Но если просто не все яснее все время.
Не должно быть удивительно, например: catch (1 / x) catch (DivisionByZero) более понятен, чем любой, если мне (в Конраде и других). Тот факт, что такого рода программирование не ожидается, является чисто условным и действительно актуальным. Может быть, в моем примере, если было бы яснее.
Но DivisionByZero и FileNotFound в этом отношении понятнее, чем ifs.
Конечно, если он менее производительный и требует миллионы раз в секунду, вы, конечно, должны его избегать, но я все же не нашел веских причин избегать общего дизайна.
Что касается принципа наименьшего удивления: здесь существует опасность круговых рассуждений: предположим, что целое сообщество использует плохой дизайн, этот дизайн станет ожидаемым! Поэтому этот принцип не может быть граалом и должен быть тщательно продуман.
Во многих реакциях как это светит корыто. Просто поймай их, нет? Ваш метод должен быть ясным, хорошо документированным и подчеркивающим его контракт. Я не понимаю этого вопроса, который должен признать.
Отладка всех исключений: то же самое, иногда это делается, потому что дизайн, не использующий исключения, является распространенным явлением. Мой вопрос был: почему это вообще распространено?
источник
x
перед звонком1/x
? 2) Оборачиваете ли вы каждую операцию деления в блок try-catch для отловаDivideByZeroException
? 3) Какую логику вы положили в блок catch для восстановленияDivideByZeroException
?openConfigFile();
может сопровождаться перехваченным FileNotFound с{ createDefaultConfigFile(); setFirstAppRun(); }
исключением FileNotFound, обработанным изящно; без сбоев, давайте сделаем опыт конечного пользователя лучше, а не хуже. Вы можете сказать: «Но что, если это был не первый запуск, и они получают это каждый раз?» По крайней мере, приложение запускается каждый раз и не вылетает при каждом запуске! На 1: 10 «это ужасно»: «первый запуск» при каждом запуске = 3 или 4, сбой при каждом запуске = 10.x
перед звонком1/x
, потому что обычно все в порядке. Исключительный случай - случай, когда это не хорошо. Мы здесь не говорим о том, как разбить землю, но, например, для простого целого числа, заданного случайным образомx
, только 1 в 4294967296 не сможет выполнить деление. Это исключение, и исключения - хороший способ справиться с этим. Тем не менее, вы можете использовать исключения для реализации эквивалентогоswitch
заявления, но это было бы довольно глупо.До исключений, в C было
setjmp
иlongjmp
может быть использовано для выполнения аналогичной развертки фрейма стека.Затем этой же конструкции было дано имя: «Исключение». И большинство ответов полагаются на значение этого имени, чтобы спорить о его использовании, утверждая, что исключения предназначены для использования в исключительных условиях. Это никогда не было целью в оригинале
longjmp
. Были только ситуации, когда нужно было разорвать поток управления на множество кадров стека.Исключения немного более общие в том смысле, что вы можете использовать их в одном и том же фрейме стека. Это поднимает аналогии с тем,
goto
что я считаю неправильным. Gotos - это тесно связанная пара (а такжеsetjmp
иlongjmp
). Исключения следуют из слабосвязанной публикации / подписки, которая намного чище! Поэтому их использование в одном и том же стековом кадре вряд ли то же самое, что использованиеgoto
s.Третий источник путаницы связан с тем, являются ли они проверенными или непроверенными исключениями. Конечно, непроверенные исключения кажутся особенно ужасными в использовании для управления потоком и, возможно, для множества других вещей.
Проверенные исключения, тем не менее, отлично подходят для управления потоком, как только вы преодолеете все викторианские зависания и немного поживете.
Мое любимое использование - это последовательность
throw new Success()
длинного фрагмента кода, который пробует одно за другим, пока не найдет то, что ищет. Каждая вещь - каждая часть логики - может иметь произвольную вложенность, поэтомуbreak
ее нет, как и любой вид условных тестов.if-else
Картина ломкая. Если я отредактируюelse
или испорчу синтаксис каким-либо другим способом, то это будет волосатая ошибка.Использование
throw new Success()
линеаризует поток кода. Я использую локально определенныеSuccess
классы - конечно, проверено - так что, если я забуду его перехватить, код не скомпилируется. И я не ловлю другой методSuccess
.Иногда мой код проверяет одну вещь за другой и только успешно, если все в порядке. В этом случае у меня есть аналогичная линеаризация с использованием
throw new Failure()
.Использование отдельной функции портит естественный уровень компартментализации. Так что
return
решение не является оптимальным. Я предпочитаю иметь одну или две страницы кода в одном месте по познавательным причинам. Я не верю в ультра тонко разделенный код.То, что делают JVM или компиляторы, не так важно для меня, если не будет горячей точки. Я не могу поверить, что есть какая-то фундаментальная причина для компиляторов не обнаруживать локально выброшенные и перехваченные исключения и просто рассматривать их как очень эффективные
goto
на уровне машинного кода.Что касается их использования в функциях для потока управления - то есть для обычных случаев, а не для исключительных случаев - я не понимаю, как они будут менее эффективны, чем множественные разрывы, тесты условий, возвраты, чтобы пройти через три кадра стека, а не просто восстановить указатель стека.
Лично я не использую шаблон для стековых фреймов, и я вижу, как для этого потребуется изысканность дизайна, чтобы сделать это элегантно. Но используется экономно, это должно быть хорошо.
Наконец, что касается удивительных девственных программистов, это не является веской причиной. Если вы аккуратно познакомите их с практикой, они научатся ее любить. Я помню, что C ++ раньше удивлял и пугал чертовых программистов.
источник
return
-Pattern альтернативы может потребоваться две функции для каждой такой функции. Внешний - для подготовки ответа сервлета или других подобных действий, а внутренний - для вычисления. PS: Английский профессор, вероятно, предложил бы использовать «удивительный», а не «удивительный» в последнем абзаце :-)Стандартный ответ заключается в том, что исключения не являются регулярными и должны использоваться в исключительных случаях.
Одна важная для меня причина заключается в том, что когда я читаю
try-catch
управляющую структуру в программном обеспечении, которое я обслуживаю или отлаживаю, я пытаюсь выяснить, почему оригинальный кодер использовал обработку исключений вместоif-else
структуры. И я ожидаю найти хороший ответ.Помните, что вы пишете код не только для компьютера, но и для других кодеров. С обработчиком исключений связана семантика, которую нельзя выбросить только потому, что машина не возражает.
источник
Как насчет производительности? Во время нагрузочного тестирования веб-приложения .NET у нас было 100 симулированных пользователей на каждый веб-сервер, пока мы не исправили часто встречающееся исключение, и это число увеличилось до 500 пользователей.
источник
Джош Блох активно занимается этой темой в «Эффективной Java». Его предложения освещают и должны относиться также к .Net (за исключением деталей).
В частности, исключения должны использоваться для исключительных обстоятельств. Причины этого в основном связаны с юзабилити. Чтобы данный метод был максимально применим, его входные и выходные условия должны быть максимально ограничены.
Например, второй метод проще в использовании, чем первый:
В любом случае вам нужно проверить, чтобы убедиться, что вызывающая сторона использует ваш API надлежащим образом. Но во втором случае это требуется (неявно). Мягкие исключения будут по-прежнему выбрасываться, если пользователь не прочитал Javadoc, но:
Основным моментом является то, что исключения не должны использоваться в качестве кодов возврата, в основном потому, что вы усложнили не только ВАШ API, но и API вызывающего.
Конечно, делать то, что нужно, дорого. Стоимость состоит в том, что каждый должен понимать, что он должен читать и следовать документации. Надеюсь, это так или иначе.
источник
Я думаю, что вы можете использовать исключения для управления потоком. Однако у этой техники есть обратная сторона. Создание исключений - вещь дорогостоящая, потому что они должны создавать трассировку стека. Поэтому, если вы хотите использовать исключения чаще, чем просто для сигнализации об исключительной ситуации, вы должны убедиться, что построение трассировки стека не окажет негативного влияния на вашу производительность.
Лучший способ сократить затраты на создание исключений - переопределить метод fillInStackTrace () следующим образом:
Такое исключение не будет заполнено.
источник
Я не очень понимаю, как вы управляете потоком программ в приведенном вами коде. Вы никогда не увидите другого исключения, кроме исключения ArgumentOutOfRange. (Таким образом, ваше второе предложение поймать никогда не будет выполнено). Все, что вы делаете, это используете чрезвычайно дорогой бросок для имитации оператора if.
Кроме того, вы не выполняете более зловещие операции, когда вы просто генерируете исключение, чтобы оно могло быть перехвачено где-то еще для управления потоком. Вы на самом деле обрабатываете исключительный случай.
источник
Вот лучшие практики, которые я описал в своем блоге :
источник
Поскольку код трудно читать, у вас могут возникнуть проблемы с его отладкой, вы будете вносить новые ошибки при исправлении ошибок по прошествии длительного времени, он будет более дорогим с точки зрения ресурсов и времени, и это раздражает вас, если вы отлаживаете свой код и отладчик останавливается при возникновении каждого исключения;)
источник
Помимо указанных причин, одной из причин не использовать исключения для управления потоком данных является то, что это может значительно усложнить процесс отладки.
Например, когда я пытаюсь отследить ошибку в VS, я обычно включаю «разбить на все исключения». Если вы используете исключения для управления потоком, то я буду регулярно ломать отладчик и буду вынужден игнорировать эти неисключительные исключения, пока не доберусь до реальной проблемы. Это может свести с ума кого-то !!
источник
Предположим, у вас есть метод, который делает некоторые вычисления. Есть много входных параметров, которые он должен проверить, а затем вернуть число больше 0.
Используя возвращаемые значения для сообщения об ошибке проверки, все просто: если метод вернул число, меньшее 0, произошла ошибка. Как тогда сказать, какой параметр не прошел проверку?
Я помню, что из моих дней C многие функции возвращали коды ошибок, например:
и т.п.
Это действительно менее читабельно, чем бросать и ловить исключение?
источник
Вы можете использовать коготь молотка, чтобы вращать винт, так же, как вы можете использовать исключения для управления потоком. Это не означает, что это предполагаемое использование функции. В
if
условиях заявления выражается, чьи направления использования является регулирование потока.Если вы используете функцию непреднамеренным образом, решив не использовать функцию, предназначенную для этой цели, это будет связано с дополнительными затратами. В этом случае ясность и производительность страдают без реальной добавленной стоимости. Что с помощью исключений покупает вас по сравнению с широко распространенным
if
утверждением?Сказал по-другому: просто потому, что вы можете , не значит, что вы должны .
источник
if
нормальное использование или использование исключений не предназначено, потому что это не предназначено (круговой аргумент)?public class ExitHelper{ public static void cleanExit() { cleanup(); System.exit(1); } }
затем просто вызовите это вместо броска:ExitHelper.cleanExit();
если бы ваш аргумент был надежным, то это был бы предпочтительный подход, и не было бы никаких исключений. Вы в основном говорите: «Единственная причина исключений - сбой другим способом».if
.Как уже неоднократно упоминали другие, принцип наименьшего удивления запрещает чрезмерное использование исключений только для целей потока управления. С другой стороны, ни одно правило не является на 100% правильным, и всегда есть случаи, когда исключением является «просто правильный инструмент» -
goto
кстати, очень похожий на самого себя, который поставляется в формеbreak
иcontinue
на таких языках, как Java, что часто являются идеальным способом выпрыгнуть из сильно вложенных циклов, которых не всегда можно избежать.Следующее сообщение в блоге объясняет довольно сложный, но также довольно интересный вариант использования для нелокального
ControlFlowException
:Это объясняет, как внутри jOOQ (библиотека абстракции SQL для Java) такие исключения иногда используются для прерывания процесса рендеринга SQL на ранних этапах, когда выполняется какое-то «редкое» условие.
Примеры таких условий:
Слишком много значений связывания. Некоторые базы данных не поддерживают произвольное количество значений связывания в своих операторах SQL (SQLite: 999, Ingres 10.1.0: 1024, Sybase ASE 15.5: 2000, SQL Server 2008: 2100). В этих случаях jOOQ прерывает фазу рендеринга SQL и повторно отображает инструкцию SQL со встроенными значениями связывания. Пример:
Если бы мы явно извлекали значения связывания из запроса AST для их подсчета каждый раз, мы бы тратили ценные циклы ЦП на те 99,9% запросов, которые не страдают от этой проблемы.
Некоторая логика доступна только косвенно через API, который мы хотим выполнить только «частично».
UpdatableRecord.store()
Метод генерируетINSERT
илиUPDATE
заявление, в зависимости отRecord
внутренних флагов «S. Со стороны мы не знаем, в какой логике содержитсяstore()
(например, оптимистическая блокировка, обработка прослушивателя событий и т. Д.), Поэтому мы не хотим повторять эту логику, когда мы храним несколько записей в пакетном операторе, где мы хотели быstore()
только генерировать оператор SQL, а не выполнять его на самом деле. Пример:Если бы мы внедрили
store()
логику в «повторно используемый» API, который можно настроить так, чтобы он не выполнял SQL, мы бы искали создание довольно сложного в обслуживании, едва ли повторно используемого API.Вывод
По сути, мы используем эти нелокальные
goto
s только в соответствии с тем, что [Mason Wheeler] [5] сказал в своем ответе:Оба использования
ControlFlowExceptions
были довольно просты в реализации по сравнению с их альтернативами, что позволило нам повторно использовать широкий спектр логики без рефакторинга ее из соответствующих внутренних компонентов.Но ощущение того, что это будет сюрпризом для будущих сопровождающих, остается. Код кажется довольно деликатным, и, хотя в данном случае это был правильный выбор, мы всегда предпочли бы не использовать исключения для локального потока управления, где легко избежать использования обычного ветвления
if - else
.источник
Обычно в этом нет ничего плохого в обработке исключений на низком уровне. Исключением является действительное сообщение, в котором содержится много подробностей о том, почему операция не может быть выполнена. И если вы можете справиться с этим, вы должны.
В общем, если вы знаете, что существует большая вероятность сбоя, который вы можете проверить ... вы должны выполнить проверку ... т.е. если (obj! = Null) obj.method ()
В вашем случае я недостаточно знаком с библиотекой C #, чтобы знать, есть ли у даты и времени простой способ проверить, не вышла ли временная метка за пределы. Если это так, просто вызовите if (.isvalid (ts)), иначе ваш код в основном в порядке.
Итак, в основном все сводится к тому, какой способ создания более чистого кода ... если операция по защите от ожидаемого исключения более сложна, чем просто обработка исключения; чем у вас есть мое разрешение обработать исключение вместо того, чтобы создавать повсюду сложные охранники.
источник
Если вы используете обработчики исключений для потока управления, вы слишком общий и ленивый. Как уже упоминалось, вы знаете, что что-то случилось, если вы обрабатываете обработку в обработчике, но что именно? По сути, вы используете исключение для оператора else, если вы используете его для потока управления.
Если вы не знаете, какое возможное состояние может возникнуть, то вы можете использовать обработчик исключений для непредвиденных состояний, например, когда вам нужно использовать стороннюю библиотеку, или вам нужно перехватить все в пользовательском интерфейсе, чтобы показать приятную ошибку сообщение и зарегистрируйте исключение.
Однако, если вы знаете, что может пойти не так, и не ставите оператор if или что-то для проверки, то вы просто ленивы. Позволить обработчику исключений быть универсальным для всего, что, как вы знаете, может произойти, лениво, и оно будет преследовать вас позже, потому что вы будете пытаться исправить ситуацию в своем обработчике исключений, основываясь на возможном ложном предположении.
Если вы добавите логику в обработчик исключений, чтобы определить, что именно произошло, то вы были бы весьма глупы, если бы не помещали эту логику в блок try.
Обработчики исключений являются последним средством, потому что, когда у вас заканчиваются идеи / способы остановить что-то, что может пойти не так, или вещи находятся за пределами вашей способности контролировать. Например, сервер не работает и время ожидания истекло, и вы не можете предотвратить создание этого исключения.
Наконец, предварительные проверки показывают, что вы знаете или ожидаете, и делают это явным. Код должен быть понятен в намерениях. Что бы вы предпочли прочитать?
источник
Возможно, вам будет интересно взглянуть на систему условий Common Lisp, которая является своего рода обобщением исключений, сделанных правильно. Поскольку вы можете разматывать стек или не контролируемым образом, вы также получаете «перезапуск», что очень удобно.
Это не имеет ничего общего с лучшими практиками на других языках, но показывает вам, что можно сделать, если придумать какой-то дизайн (примерно) в том направлении, о котором вы думаете.
Конечно, по-прежнему существуют соображения производительности, если вы подпрыгиваете вверх и вниз по стеку, как йо-йо, но это гораздо более общая идея, чем подход «о, дерьмо, позволяет залог», который воплощает большинство систем исключений catch / throw.
источник
Я не думаю, что есть что-то не так с использованием исключений для управления потоком. Исключения чем-то похожи на продолжения, и в статически типизированных языках исключения являются более мощными, чем продолжения, поэтому, если вам нужны продолжения, но в вашем языке их нет, вы можете использовать исключения для их реализации.
Ну, на самом деле, если вам нужны продолжения, а у вашего языка их нет, вы выбрали не тот язык, и вам лучше использовать другой. Но иногда у вас нет выбора: клиентское веб-программирование - это главный пример - просто невозможно обойти JavaScript.
Пример: Microsoft Volta - это проект, позволяющий писать веб-приложения в прямом .NET и позволяющий платформе позаботиться о том, какие биты должны выполняться и где. Одним из следствий этого является то, что Volta должна иметь возможность компилировать CIL в JavaScript, чтобы вы могли запускать код на клиенте. Однако есть проблема: .NET имеет многопоточность, а JavaScript - нет. Итак, Volta реализует продолжения в JavaScript с использованием исключений JavaScript, а затем реализует потоки .NET, используя эти продолжения. Таким образом, приложения Volta, использующие потоки, могут быть скомпилированы для запуска в неизмененном браузере - Silverlight не требуется.
источник
Одна эстетическая причина:
Попытка всегда идет с уловом, тогда как если не нужно идти с другим.
С try / catch это становится намного более многословным.
Это 6 строк кода слишком много.
источник
Но вы не всегда будете знать, что происходит в методах, которые вы вызываете. Вы не будете точно знать, где было выброшено исключение. Без изучения объекта исключения более подробно ....
источник
Я чувствую, что в вашем примере нет ничего плохого. Напротив, было бы грехом игнорировать исключение, создаваемое вызываемой функцией.
В JVM создание исключения не так уж и дорого, только создание исключения с новым xyzException (...), потому что последнее включает в себя обход стека. Поэтому, если у вас есть заранее созданные исключения, вы можете бросить их много раз без затрат. Конечно, таким образом вы не можете передавать данные вместе с исключением, но я думаю, что это в любом случае плохо.
источник
Существует несколько общих механизмов, с помощью которых язык может позволить методу завершать работу, не возвращая значения, и возвращаться к следующему блоку «catch»:
Попросите метод проверить кадр стека, чтобы определить сайт вызова, и использовать метаданные для сайта вызова, чтобы найти либо информацию о
try
блоке в вызывающем методе, либо место, где вызывающий метод сохранил адрес своего вызывающего; в последнем случае изучите метаданные для вызывающего абонента, чтобы определить его так же, как непосредственного вызывающего, повторяя, пока не будет найденtry
блок или стек не пуст. Этот подход добавляет очень мало накладных расходов к случаю без исключений (он исключает некоторые оптимизации), но стоит дорого, когда возникает исключение.Пусть метод вернет «скрытый» флаг, который отличает нормальный возврат от исключения, и пусть вызывающий проверит этот флаг и ответвление на процедуру «исключение», если она установлена. Эта подпрограмма добавляет 1-2 инструкции к случаю без исключения, но относительно небольшую нагрузку при возникновении исключения.
Пусть вызывающий абонент разместит информацию или код обработки исключений по фиксированному адресу относительно сложенного обратного адреса. Например, с ARM вместо использования инструкции «BL-подпрограмма» можно использовать последовательность:
Чтобы выйти нормально, подпрограмма просто сделала бы
bx lr
илиpop {pc}
; в случае ненормального выхода подпрограмма должна либо вычесть 4 из LR перед выполнением возврата или использованияsub lr,#4,pc
(в зависимости от вариации ARM, режима выполнения и т. д.). Этот подход будет работать очень плохо, если вызывающая сторона не предназначена для его размещения.Язык или инфраструктура, в которых используются проверенные исключения, могут выиграть от того, что они обрабатываются с помощью механизма, подобного # 2 или # 3 выше, в то время как непроверенные исключения обрабатываются с использованием # 1. Хотя реализация проверенных исключений в Java довольно неприятна, они не были бы плохой концепцией, если бы существовал способ, с помощью которого сайт вызова мог бы сказать, по сути, «Этот метод объявлен как выбрасывающий XX, но я не ожидаю этого когда-нибудь сделать это, если это произойдет, перебросить как «непроверенное» исключение. В среде, где проверенные исключения обрабатывались таким образом, они могут быть эффективным средством управления потоком для таких вещей, как методы синтаксического анализа, которые в некоторых контекстах могут иметь высокая вероятность неудачи, но там, где неудача должна возвращать информацию, принципиально отличную от успеха. Однако я не знаю каких-либо фреймворков, использующих такой шаблон. Вместо этого, более распространенной моделью является использование первого подхода, описанного выше (минимальная стоимость для случая без исключения, но высокая стоимость, когда создаются исключения) для всех исключений.
источник