Вопрос обработки исключений - PullRequest
32 голосов
/ 22 февраля 2010

У меня есть вопрос относительно обработки исключений. Рассмотрим следующий фрагмент кода 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
            }
        }

Может кто-нибудь сказать мне недостатки второго подхода?

Ответы [ 8 ]

111 голосов
/ 22 февраля 2010

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

40 голосов
/ 22 февраля 2010

Да, MadMurf указывает на самое важное отличие: проверка достижимости во время компиляции.Стандартная идиома поймает что-то вроде этого и по праву предотвратит компиляцию:

    try {
    } catch (IndexOutOfBoundsException iooe) {
    } catch (ArrayIndexOutOfBoundsException aiooe) {
    }

Компилируется аналог if / instanceof, предложенный в исходном вопросе (это НЕ то, что вы хотели бы, потому что он ошибочен).

Причина, по которой стандартная идиома отлавливает ошибку во время компиляции, приведена в JLS 14.21 Недоступные заявления .

  • Достигнут блок перехвата Cесли оба следующих условия верны:
    • [...]
    • Нет более раннего блока catch A в операторе try, так что тип параметра C такой же, как у подкласса илитипа параметра А.

Чтобы дополнительно проиллюстрировать эту точку, следующие компиляции:

    try {
    } catch (Exception e) {
        if (e instanceof Exception) {
        } else if (e instanceof Exception) {
        }
    }

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

Чтобы еще яснее понять, сделали ли вынамеренно или нет, вы фактически изменили порядок, в котором вы проверяли исключения в исходном вопросе, и этот факт мог быть легко пропущен другими.Если SubSubException является подклассом SubException, второе условие if НИКОГДА не будет оцениваться, а его тело является фактически недоступным кодом.

Подход if / instanceof ОЧЕНЬ подвержен ошибкам.

23 голосов
/ 22 февраля 2010

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

4 голосов
/ 22 февраля 2010

Второй подход значительно менее читабелен, потому что:

  • требуется больше символов,

  • требуется более глубокий отступ,

  • это не идиоматично.

И ИМО, последнее наиболее важно. Вы должны писать свой код так, как другие Java-программисты ожидают его написания.

4 голосов
/ 22 февраля 2010

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

2 голосов
/ 22 февраля 2010

В качестве альтернативы при повторном заказе «ловли» исключений во втором примере. Если SubSubException расширяет SubException, вторая проверка никогда не будет достигнута ...

просто нужно с осторожностью относиться к заказу уловов ...

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

1 голос
/ 04 июля 2011

Я думаю, лучше (гораздо читабельнее):

 try {    
   .....
 } 
 catch (IndexOutOfBoundsException iooe) {    } 
 catch (ArrayIndexOutOfBoundsException aiooe) {    }
 .....

и

  try {
     .....
  } 
  catch (Exception e) {
     if (e instanceof Exception) {        } else 
     if (e instanceof Exception) {        } else
     .....
  }
1 голос
/ 22 февраля 2010

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

Недостатки: - Труднее понять

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