Если перехват исключения нулевого указателя не является хорошей практикой, является ли перехват исключения хорошей?
Я слышал, что ловить NullPointerException
это плохая практика, и я думаю, что это разумно. Позволяя NullPointerException
распространение на вершину позволило бы обнаружить, что что-то идет не так. Но много раз я видел, как многие из моих друзей ловили Exception
непосредственно, так что им не нужно беспокоиться обо всех видах исключений, которые могут возникнуть в приведенном выше коде. Это хорошая практика? Какие другие виды исключений лучше оставить необработанными? И кроме того, это также имеет смысл для меня, чтобы справиться NullPointerException
над конкретным кодом, где мы уверены в источнике исключения. Так когда же обрабатывать исключения и когда их не следует обрабатывать? И каков был бы возможный список исключений, которые лучше всего оставить необработанными?
6 ответов
Обработка исключений покемонов это плохо. Особенно, если это пустой блок, и вы просто глотаете их. У вас есть специально введенные исключения по той причине, что они на самом деле означают конкретные вещи в определенных контекстах (по сути, они говорят вам, что пошло не так). Итак, поймав Exception
Вы говорите, что вам все равно, что это за исключения, и что вам все равно, что случилось. Это, вероятно, не то, что вы хотите.
В общем, при отлове исключений соблюдайте следующие правила:
- Имеет ли смысл обрабатывать исключения на этом уровне? Если да, то справиться с этим. Если нет, то размножайтесь.
- В сочетании с первым правилом "обработка" также может означать "захват", "обертывание" и "перебрасывание". Это способ предотвратить утечку абстракции, так что вызывающие ваши методы не должны знать о базовой реализации.
- Пустой блок catch не означает, что вы обработали исключение. Это называется "глотание"; по крайней мере, вы хотите записать исключение. Иногда происходящее исключение на самом деле является частью логического потока вашего кода, и поэтому вы можете захотеть сделать что-то особенное (но это, простите за каламбур, скорее исключение, чем правило. Лучше проверять ситуации, которые вызывают исключения). вместо того, чтобы включать их в логический поток вашего кода).
Вы можете легко проверить нулевое значение в своем коде, поэтому нет необходимости явно перехватывать исключение нулевого указателя. Нет смысла позволять NullPointerException
случиться (и это плохая практика). Даже если у вас есть код, который бросает NullPointerException
и это код, который вы не контролируете и не можете исправить, вы должны определить входные параметры, которые вызывают NullPointerException
и специально тест для них.
Еще одно исключение, которое вы не должны ловить, это IllegalArgumentException
, Это исключение означает, что вы передали аргумент, который не имеет смысла. Вместо того, чтобы перехватывать это исключение, вы должны явно проверить ваши входные параметры, чтобы убедиться, что они нормальные и не могут вызвать IllegalArgumentException
,
"Причина", что ловить NullPointerException
Это считается плохой практикой не потому, что вы должны позволить этому пузыриться, когда что-то идет не так! Сказать, что любое исключение "лучше оставить необработанным", основываясь только на его типе, кажется плохой идеей.
NPE считается результатом ошибки программирования. Строго правильная программа никогда не должна генерировать ее. Причина, по которой он пойман, плохая, потому что обычно это означает, что код его сгенерировал, и программист решил просто поймать его и скрыть, а не исправлять испорченный код, вызвавший его в первую очередь!
Если, например, вы были по деловым причинам связаны с API, в котором есть ошибка и иногда выбрасывает нулевой указатель, было бы вполне законно его перехватить, что-то сделать с этим или проинформировать пользователя с лучшим сообщением. Разрешение 'null' ударить по интерфейсу только потому, что кто-то сказал, что "Catching Null Pointer Exception is bad" не имеет смысла!
ловля java.lang.Exception
может быть законным в определенных случаях, но, как правило, "я ленивый" не является одним из них.:) Например, если вы реализуете API и хотите быть абсолютно уверенным, что из него никогда не выйдет исключение, которого нет в спецификации, вы можете перехватить Exception и обернуть его в определенное вами исключение приложения.
Вы должны поймать Исключение только в том случае, если вы можете добавить некоторую ценность, делая это. В противном случае вы должны позволить это передать вызывающему.
NullPointerException обычно является результатом ошибки в вашем коде. Как вы можете разумно исправить это в блоке catch?
Не беспокоиться об исключениях - это не хорошая практика.
В общем, единственное время, когда вы должны поймать исключение, это если вы можете обработать его осмысленным образом. Если вы не можете, просто дайте ему взорваться и завершите процесс. Например, не могли бы вы каким-то значительным образом исправить ошибку NullPointerException или ошибку ввода-вывода? Думаю, нет.
Мои правила обработки исключений:
- В общем, не перехватывайте исключения, если вы не можете обрабатывать их осмысленно.
- Поймать исключения на границах процесса / компьютера, зарегистрировать перехваченное исключение вместе с любым доступным вам контекстом и перезапустить его. Если исключение является пользовательским исключением, вы можете заключить его в исключение типа, известного / полезного для вызывающего процесса, и выбросить его.
- Вы также можете перехватывать исключения на низком уровне, где у вас есть максимально доступный контекст времени выполнения, регистрировать исключение и связанный с ним контекст, а затем перебрасывать исключение.
- При перебрасывании используйте
throw ;
скорее, чемthrow caughtException ;
, Использование прежнего синтаксиса сохраняет исходную трассировку стека; использование последнего синтаксиса создает новую трассировку стека, начиная сthrow caughtException ;
- вы теряете весь контекст и вызываете стек до точки, в которой было обнаружено исключение. - Вы можете по своему усмотрению перехватывать исключения на высоком уровне и корректно завершать процесс, регистрируя информацию об исключениях, чтобы помочь отладить и исправить основную проблему.
Не используйте исключения в качестве механизма управления потоком (если это возможно). Предполагается, что исключения должны быть исключительными по своей природе. Скорее, принудительно обеспечьте конец контракта вызывающей стороны (предварительные условия) для любых методов, которые вы вызываете.
См. Книгу Бертранда Мейерса " Конструирование объектно-ориентированного программного обеспечения", 2-е изд. для дополнительной информации.
Основное правило при отлове исключений заключается в том, что вы должны знать, почему вы это делаете. Класс исключений отлавливается в тех случаях, когда программист хочет выполнить общую обработку ошибок, и ему на самом деле все равно, что именно произошло, главное, что что-то пошло не так. В этом случае он может решить откатить транзакцию или выполнить некоторую очистку. Если вы ловите конкретное исключение, попробуйте применить то же правило. Если вы точно знаете, для чего вы это делаете, то это для этого. Но это очень редкий случай, когда кто-то захочет сделать что-то действительно особенное в случае NPE.
Если у вас есть изящный способ обработки вашего исключения, полезно его перехватить, если не надеетесь, что у вызывающего абонента есть хороший способ его обработать.