Вопрос об обработке исключений
У меня вопрос об обработке исключений.
Рассмотрим следующий фрагмент кода Java.
try{
//code
}catch(SubSubException subsubex){
//code
}catch(SubException subex){
//code
}catch(Exception ex){
//code
}
Я знаю, что это рекомендуемый способ обработки исключений. Но я могу добиться того же, используя следующий фрагмент кода.
try{
//code
}catch ( Exception ex){
if( ex instanceof SubException){
//code
}else if(ex instanceof SubSubException){
//code
}else{
//code
}
}
Может кто-нибудь сказать мне недостатки второго подхода?
Ответы
Ответ 1
Второй подход менее читабельен. Кроме того, обработка исключений Pokemon никогда не проходит, хотя ваш "умный" трюк заключается в использовании ключевого слова instanceof. Я вообще не шучу и не издеваюсь над вами, но лучше всего писать код для людей, чтобы читать и поддерживать, а не для компьютера.
Ответ 2
Да, MadMurf указывает на самое важное различие: проверка доступности на время компиляции. Стандартная идиома поймала бы что-то вроде этого и по праву помешала бы ее компиляции:
try {
} catch (IndexOutOfBoundsException iooe) {
} catch (ArrayIndexOutOfBoundsException aiooe) {
}
Если/instanceof аналога, предложенного в исходном вопросе, будет компилироваться (что НЕ является тем, что вы хотите, потому что оно ошибочно).
Причина, по которой стандартная идиома ловит ошибку во время компиляции, приведена в JLS 14.21 Недоступные сообщения.
- Блок catch C доступен, если выполняются оба следующих условия:
- [...]
- В заявлении try нет ранее блока catch A, так что тип параметра C совпадает с подклассом типа параметра A.
Чтобы проиллюстрировать эту точку, следующие компиляции:
try {
} catch (Exception e) {
if (e instanceof Exception) {
} else if (e instanceof Exception) {
}
}
Как вы можете видеть, эту "ипокуму" покемонов гораздо сложнее поддерживать, потому что она обходит некоторые из проверок достижимости времени компиляции, применяемых в стандартной идиоме.
Чтобы сделать пункт еще более ясным, независимо от того, сделали ли вы это специально или нет, вы фактически перестроили порядок, в котором вы проверяли исключения в вашем исходном вопросе, что может быть легко упущено другими. Если SubSubException является подклассом SubException, второе условие if НИКОГДА не будет оцениваться, а его тело будет действительно недостижимым.
Подход if/instanceof ОЧЕНЬ подвержен ошибкам.
Ответ 3
hmm, почему вы даже должны сделать второй подход? помните это, если другие варианты не лучше с точки зрения производительности, удобочитаемости и т.д., вы должны придерживаться конвенций. catch были первоначально разработаны таким образом, чтобы они обрабатывали классификацию типов исключений, владеющих собственными, поэтому используйте их как... просто мысль!...
Ответ 4
Второй случай - это абсолютно корректный Java-код, но он имеет более крупный Cyclomatic complex без добавления дополнительного значения.
Ответ 5
Второй подход значительно менее читабельен, потому что:
-
для этого требуется больше символов,
-
требуется более глубокое отступы,
-
это не идиоматично.
И ИМО, последнее самое важное. Вы должны писать свой код таким образом, чтобы другие программисты Java ожидали, что он будет написан.
Ответ 6
Как и в случае переупорядочения ваших "ловушек" исключений в вашем втором примере. Если SubSubException расширяет SubException, вторая проверка никогда не будет достигнута....
просто нужно быть осторожным при заказе ваших уловов...
кроме того, как упоминалось в другом месте, вопрос должен был бы быть причиной того, почему второй способ, когда первый работает, является стандартным и читаемым?
Ответ 7
Учитывая, что код в первом блоке проверяет тип исключения, проверяйте базовое исключение один раз (во втором бите кода, который вы тестируете для базового исключения в два раза) и меньше с отступом (таким образом, меньше логики для grok), я думаю, что первый из них намного приятнее, легче понять и т.д.
Недостатки:
- Труднее понять
Ответ 8
Я думаю, лучше (много читаемо):
try {
.....
}
catch (IndexOutOfBoundsException iooe) { }
catch (ArrayIndexOutOfBoundsException aiooe) { }
.....
и
try {
.....
}
catch (Exception e) {
if (e instanceof Exception) { } else
if (e instanceof Exception) { } else
.....
}