Вопрос об обработке исключений

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

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

32
задан Upul Bandara 22 February 2010 в 05:21
поделиться

7 ответов

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

111
ответ дан 27 November 2019 в 19:38
поделиться

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

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

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

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

  • Блок 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 ОЧЕНЬ склонен к ошибкам.

40
ответ дан 27 November 2019 в 19:38
поделиться
let process_output_to_list2 = fun command -> 
  let chan = Unix.open_process_in command in
  let res = ref ([] : string list) in
  let rec process_otl_aux () =  
    let e = input_line chan in
    res := e::!res;
    process_otl_aux() in
  try process_otl_aux ()
  with End_of_file ->
    let stat = Unix.close_process_in chan in (List.rev !res,stat)
let cmd_to_list command =
  let (l,_) = process_output_to_list2 command in l
-121--3060823-

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

4
ответ дан 27 November 2019 в 19:38
поделиться

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

23
ответ дан 27 November 2019 в 19:38
поделиться

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

  • он требует большего количества символов,

  • он требует более глубокого отступа,

  • он не является идиоматическим.

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

4
ответ дан 27 November 2019 в 19:38
поделиться

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

только то, что нужно насторожить при заказе ваших уловов...

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

2
ответ дан 27 November 2019 в 19:38
поделиться

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

Недостатки: - Сложнее понять

{{1 }}
1
ответ дан 27 November 2019 в 19:38
поделиться
Другие вопросы по тегам:

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