Почему Поймать (Исключение) почти всегда плохая идея? - PullRequest
53 голосов
/ 10 марта 2010

Почему catch(Exception) почти всегда плохая идея?

Ответы [ 10 ]

56 голосов
/ 10 марта 2010

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

Основной принцип - ловить наиболее конкретный тип, который вы можете.

18 голосов
/ 10 марта 2010

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

8 голосов
/ 10 марта 2010

Вы должны ловить исключения, только если вы можете правильно их обработать. Поскольку вы не можете правильно обработать все возможные исключения, вы не должны их ловить: -)

5 голосов
/ 10 марта 2010

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

Следовательно, вы должны ловить только исключения:

  • что вы точно знаете, как с этим справиться (например, FileNotFoundException или около того)
  • когда вы будете поднимать их позже (например, для выполнения очистки после сбоя)
  • когда вам нужно перенести исключение в другой поток
4 голосов
/ 10 марта 2010

Это зависит от того, что вам нужно. Если вам нужно обрабатывать различные типы исключений по-разному, вам следует использовать несколько блоков catch и перехватывать как можно больше конкретных исключений.

Но иногда вам может понадобиться обрабатывать все исключения одинаково. В таких случаях catch (Exception) может быть в порядке. Например:

    try
    {
        DoSomething();
    }
    catch (Exception e)
    {
        LogError(e);
        ShowErrorMessage(e); // Show "unexpected error ocurred" error message for user.
    }
3 голосов
/ 09 февраля 2018

Я нахожу два приемлемых варианта использования catch(Exception):

  • На верхнем уровне приложения (непосредственно перед возвратом к пользователю). Таким образом, вы можете предоставить адекватное сообщение.
  • Использование его для маскировки низкоуровневых исключений как бизнес-исключений.

Первый случай не требует пояснений, но позвольте мне развить второй:

Выполнение:

try {
    // xxxx
} catch(Exception e) {
    logger.error("Error XXX",e)
}

- это маскировка ошибок, как сказал @dimitarvp.

Но ниже все по-другому:

try {
    // xxxx
} catch(Exception e) {
    throw new BussinessException("Error doing operation XXX",e)
}

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

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

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

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

Если в блоке кода вы можете получить SQLException и NetworkException, вы должны поймать их и предоставить адекватные сообщения и обработку для каждого из них. Но если в конце блока try / catch у вас есть Exception, отображающий его на BussinessException, это нормально для меня. На самом деле, я считаю это адекватным, когда более высокие уровни обслуживания только генерируют бизнес-исключения (с подробностями внутри).

1 голос
/ 27 ноября 2015

Кроме того, что еще ответил @anthares:

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

Основной принцип - поймать наиболее конкретный тип, который вы можете.

catch(Exception) - плохая практика, поскольку она также перехватывает все RuntimeException (непроверенное исключение).

0 голосов
/ 31 августа 2018

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

Thread shouldRunWhenApplicationRuns = new Thread() {
    @Override
    public void run() {
        try {
            // do something that should never end
        } catch (Exception ex) {
            // log it
        }
    };
    shouldRunWhenApplicationRuns.start();
0 голосов
/ 01 июля 2016

Но иногда это нормально! Например, если у вас есть кусок кода, который делает что-то «лишнее», что вас действительно не волнует, и вы не хотите, чтобы он взорвал ваше приложение. Например, недавно я работал над большим приложением, где наши деловые партнеры хотели, чтобы определенная ежедневная транзакция была обобщена в новом файле журнала. Они объяснили, что журнал не так уж важен для них, и что он не может считаться требованием. Это было просто нечто дополнительное, что помогло бы им разобраться в обрабатываемых данных. Им это не нужно, потому что они могут получить информацию в другом месте. Так что это редкий случай, когда совершенно нормально ловить и глотать исключения.

Я также работал в компании, где все Throwables были пойманы, а затем переброшены в пользовательскую исключительную ситуацию RuntimeException. Я бы не рекомендовал такой подход, а просто указав, что он сделан.

0 голосов
/ 12 марта 2014

Это может быть специфично для Java:

Иногда вам нужно будет вызывать методы, которые выдают проверенные исключения. Если это на уровне EJB / бизнес-логики, у вас есть 2 варианта - поймать их или перебросить их.

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

Перебрасывание означает, что код, вызывающий ваши EJB, будет усеян перехватом кода, который обычно ничего не будет значить для вызывающего класса. нотабене Выдача проверенных исключений из методов EJB будет означать, что вы отвечаете за откат всех транзакций вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...