Почему Java имеет и проверенные и неконтролируемые исключения? [дубликат]

BatchSubstitute.bat на dostips.com пример поиска и замены с помощью чистого пакетного файла.

Это использует комбинацию FOR, FIND и CALL SET.

Строки, содержащие символы среди "&<>]|^, можно рассматривать неправильно.

5
задан Community 23 May 2017 в 10:32
поделиться

6 ответов

Теория проверенных исключений проста.

При разработке интерфейса подумайте об исключительных случаях, которые могут произойти и будут происходить в нормальном состоянии вызова метода. Объявите эти исключения в своем интерфейсе, так как программист должен будет обрабатывать их напрямую.

Например, метод снятия с банковского счета может объявлять OverdraftException, что является ожидаемым исключением - снятие средств может завершиться неудачно из-за овердрафта, но этот тип Код сбоя может обрабатываться по-разному с помощью кода клиента (один может решить полностью отказаться от вывода средств, другой может решить применить огромный штраф и разрешить запись отрицательного баланса, другой может решить, что его клиенту разрешено использовать другая учетная запись).

Однако исключения времени выполнения должны были быть ошибками программирования, которые не были t предполагается, что они обрабатываются напрямую - такие как NullPointerExceptions, которые возникают только в том случае, если методы принимают недопустимые аргументы или не проверяют такие случаи напрямую.

Это хорошая теория. Однако Java испортила свою реализацию исключений, и это выбросило книгу этой теории из окна.

Я проиллюстрирую два случая, когда Java испортилась со своей реализацией исключений. Это IOException и SQLException.

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

Но есть еще кое-что.

IOException также скрывает такие вещи, как исключения файлов и исключения сети. Они могут быть подклассами IOException, плавающими для этого, но это все же проверенное исключение. Если ваша запись во внешний файл не удалась, вы ничего не можете с этим поделать - если ваше сетевое соединение разорвано, то же самое.

SQLException - то же самое. Имена исключений должны показывать, что произошло при их вызове. SQLException - нет. SQLException генерируется каждый раз, когда при работе с базой данных встречается любое возможное количество ошибок - БОЛЬШИНСТВО из которых НЕ ИМЕЕТ НИЧЕГО СВЯЗИ С SQL.

Поэтому программисты обычно раздражаются обработкой исключений и позволяют Eclipse (или любой другой среде IDE) они используют) генерируют такие блоки:

try {
thisMethodThrowsACheckedExceptionButIDontCare();
}
catch(Exception e) {
e.printStackTrace();
}

Однако с RuntimeExceptions, они намеренно всплывают и в конечном итоге обрабатываются на уровне JVM или контейнера. Это хорошо - это приводит к появлению ошибок, а затем вы должны исправить код напрямую, а не игнорировать исключение - вы все равно можете просто распечатать трассировку стека (надеюсь, записать ее вместо прямой печати на консоль), но тогда будет обработчик исключений, который вы были вынуждены написать из-за реальной проблемы - не потому, что метод сказал, что он может , возможно, вызвать исключение, но что он сделал.

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

14
ответ дан 18 December 2019 в 05:36
поделиться

Лично я считаю, что проверенные исключения были ошибкой в ​​Java.

Помимо этого, обозначение как проверенных, так и непроверяемых исключений позволяет библиотеке различать восстанавливаемые и неисправимые ошибки. Создавая для всех исправимых ошибок проверенные исключения, библиотека / язык может заставить разработчика обрабатывать крайние случаи, которые в противном случае могли бы затереть.

Большая проблема с этим:

try{
  myCode();
}catch(Exception e){ //Do nothing }

Кроме того, в большинстве случаев действительно лучше просто поднимите руки и передайте исключение, когда оно произойдет. Принудительно объявляя проверенные исключения, метод, который действительно не заботится о возникновении ошибки, в конечном итоге имеет зависимости (с точки зрения совместимости, но также запах кода и другие), которых на самом деле не должно быть.

5
ответ дан 18 December 2019 в 05:36
поделиться

Отмеченные и непроверенные исключения вызывают немного религиозный аргумент - Java упала с одной стороны, C # - с другой.

В Java следует использовать проверенные исключения, когда вызывающий код может восстановить из ошибки, где непроверенные исключения используются при возникновении критической ошибки (возможно, за исключением NullPointerException ), от которой вызывающий код вряд ли сможет восстановить.

Лично Я предпочитаю, чтобы оба были доступны для меня, и я предпочитаю проверенные исключения, потому что они позволяют мне заставить вызывающий код работать с ошибочной ситуацией, которую разработчик мог бы в противном случае проигнорировать (хотя печально известный пустой блок catch помогает избежать этого).

4
ответ дан 18 December 2019 в 05:36
поделиться

Я думаю, что Sun изначально подумала, что это будет хорошая идея, потому что программист вынужден обрабатывать исключение. Однако, много лет спустя, почти все согласны с тем, что это плохое и ненужное дополнение.

Одна из основных проблем (помимо загромождения кода) заключается в том, что они пропускают абстракции с нижних уровней на более высокие уровни (например, удаленные исключения rmi)

3
ответ дан 18 December 2019 в 05:36
поделиться

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

Например, для программы может быть разумным обрабатывать неверный ввод от пользователя, но если что-то пойдет не так с базовой ОС и потоки начнут умирать без причины, это не то, что программа следует ожидать обработки.

5
ответ дан 18 December 2019 в 05:36
поделиться

Я не думаю, что есть что-то концептуально неправильное с проверенными исключениями ... но на практике они имеют тенденцию сильно отстой, потому что (особенно ранние) разработчики библиотек злоупотребляют ими.

Также требование «поймать или объявить» НЕ подходит для интерфейсов.

Мои основные мысли таковы: «Что-то идет не так» бывает двух основных видов: восстанавливаемое и невосстановимое ... Ergo: Бизнес-исключения и Системные ошибки.

Например: что вы (разработчик библиотеки) ожидаете от меня (прикладного программиста) для восстановления после сбоя при вызове SomeStream. близко()? Да, я определенно должен знать, что что-то пошло не так, но на самом деле мой единственный вариант - завершить программу / запрос / процесс / поток, который споткнулся о нем. Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

  • интерфейс Throwable Мне определенно нужно знать, что что-то пошло ужасно неправильно, но на самом деле мой единственный вариант - завершить программу / запрос / процесс / поток, который споткнулся о нем. Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

    Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

    • интерфейс Throwable Мне определенно нужно знать, что что-то пошло ужасно неправильно, но на самом деле мой единственный вариант - завершить программу / запрос / процесс / поток, который споткнулся о нем. Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

      Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

      • интерфейс Throwable но на самом деле мой единственный вариант - завершить программу / запрос / процесс / поток, который споткнулся о него. Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

        Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

        • интерфейс Throwable но на самом деле мой единственный вариант - завершить программу / запрос / процесс / поток, который споткнулся о него. Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

          Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

          • интерфейс Throwable Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

            Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

            • интерфейс Throwable Я не могу разумно ожидать, что я даже попытаюсь оправиться от ситуации ... Ergo: Это неисправимая ошибка, и поэтому меня не следует заставлять писать много очень репутационных шаблонных блоков-ловушек, которые не работают Не справляюсь с проблемой на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

              Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

              • интерфейс Throwable • обрабатывать проблему на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

                Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

                • интерфейс Throwable • обрабатывать проблему на каждом уровне (потенциально очень глубокого) стека вызовов. Поэтому я считаю, что было бы лучше, если бы "ловить все" проверенные исключения, такие как IOException, никогда не изобрели ... CloseException extends UncheckedIOException было бы более подходящим, ИМХО.

                  Кроме того, если бы у меня была машина времени, я бы вернулся вовремя и умолять богов Java:

                  • интерфейс Throwable
                    • Исключение абстрактного класса
                      • абстрактный класс CheckedException
                      • абстрактный класс UncheckedException
                    • class Error

                  Также: я бы хотел увидеть аннотацию класса @FaultBarrier, которая заставляет компилятор применять: все исключения (особенно непроверенные) должны быть пойман или явно брошен. Самый ужасный кусок системы, над которым я когда-либо работал, был пронизан выбросами необработанных исключений RuntimeException; Этого достаточно, чтобы заставить тебя плакать.

                  Ура. Кейт.

1
ответ дан 18 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: