Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 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
     .....
  }