Melhores práticas para o tratamento de exceções Java

eu escrevi o seguinte código recentemente; ele usa um monte de tratamento de exceção. Acho que faz o código parecer muito ilegível. Eu poderia encurtar o código pegando exceção genérica, como

catch (Exception e){
    e.printStackTrace();
}
Mas também ouvi dizer que a captura de uma excepção genérica não é uma boa prática de codificação.

public class DataAnalyzerTester {
    /**
     * @param args args[0] stores the filename
     * @exception NoSuchElementException if user attempts to access empty list element
     * @exception ArithmeticException if user attempts to divide by 0
     * @exception ArrayIndexOutOfBoundsException if user supplied less than 3 arguments
     * @exception IOException problems with creating and writing files
     * @exception RuntimeException if user attempts to pass empty list to constructor
     */
    public static void main(String[] args) {

    try{
        //some code

    } catch (NoSuchElementException e) {
        System.out.println("Accessing element that does not exist: " + e.toString());
    } catch (ArithmeticException e) {
        System.out.println("Division by zero: " + e.toString());
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Please supply a command line arguement that specifies your file path: " + e.toString());
    } catch (IOException e) {
        System.out.println("Other IO errors: " + e.toString());
    } catch (RuntimeException e) {
        System.out.println(e.toString());
    } 
    }
}
Gostaria de saber se há uma maneira melhor e mais limpa de apanhar várias excepções.

Author: Guan Summy Huang, 2015-09-13

2 answers

Primeiro, a não ser que tenhas Muito boa razão, nunca apanhe.RuntimeException, Exception ou Throwable. Estes vão apanhar a maior parte do que for lançado, e {[3] } vão apanhar Tudo, mesmo aquelas coisas que não estás destinado a apanhar, tipo ...

Em segundo lugar, evite pegar exceções de tempo de execução a menos que impeça diretamente com o funcionamento crítico do seu programa. Mas a sério, se alguém te vê a apanhar um, eles estão lá dentro. têm todo o direito de te chamar.) As únicas exceções que você deve estar incomodando com são aquelas que você é obrigado a lidar. Fora da sua lista de excepções, o único com quem você deve preocupar-se é com IOException. O resto são o resultado de testes não suficientes, ou codificação desleixada; esses não devem ocorrer no tempo de execução normal de sua aplicação.

Em Terceiro Lugar, em Java 7, você tem a capacidade de fazer ummulti-catch para as suas exceções, se as exceções são exclusivo. O exemplo ligado faz um bom trabalho em explicá - lo, mas se você fosse encontrar um código que jogasse tanto um IOException quanto um SQLException, Você poderia lidar com isso assim:

try {
    // Dodgy database code here
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}
Isto limpa um pouco as coisas, já que não tens grandes e pesadas cadeias de excepções para apanhar.
 12
Author: Makoto, 2015-09-13 01:03:45
Em primeiro lugar, o problema dos Conselhos de "melhores práticas" é que tende a simplificar excessivamente a pergunta e a resposta. Então alguém (como você) aparece e percebe que é contraditório. IMO, as melhores práticas são seguir os conselhos de "melhores práticas" e as pessoas que utilizam regularmente essa frase com um nível saudável de suspeita. Tente entender as questões reais você mesmo, e chegar às suas próprias conclusões ... em vez de depender de outra pessoa para lhe dizer o que é "melhor" pratica".
Qual é o problema? É esta declaração:
Mas também ouvi dizer que a captura de uma excepção genérica não é uma boa prática de codificação.

De facto, não é normalmente a boa prática de codificação para apanhar excepções genéricas comoException. Mas é a coisa certa a fazer em algumas circunstâncias. E o seu exemplo é aquele em que é apropriado.

Porquê? Vamos ver um caso em que apanhar é mau. ideia:
    public void doSomething(...) {
        try {
            doSomethingElse(...);
        } catch (Exception ex) {
            // log it ... and continue
        }
    }
Porque é que isso é uma má ideia? Porque isso catch vai pegar e manusearexcepções inesperadas ; isto é, excepções que você (o desenvolvedor) não pensou que fossem possíveis, ou que você nem sequer considerou. Não faz mal ... mas depois o código regista a excepção, e continua a correr como se nada tivesse acontecido. Esse é o verdadeiro problema ... a tentar recuperar de uma excepção inesperada .

O conselho de "melhores práticas" para "nunca pegar exceções genéricas" lida com o problema, mas de uma forma grosseira que não lida com os casos de borda. Um dos casos de aresta é que capturar (e registrar) uma exceção genérica é OK se você, em seguida, desligar imediatamente a aplicação ... como estás a fazer.

    public void main(...) {
        try {
            // ...
        } catch (Exception ex) {
            // log exception
            System.err.println("Fatal error; see log file");
            System.exit(1);
        }
    }
Agora contrasta com a (supostamente) versão de boa prática na tua pergunta. Qual é a diferença?
    A sua versão produz diagnósticos mais fáceis de utilizar ou menos alarmantes ... até a ponto.
  1. a tua versão é significativamente mais código.
  2. A tua versão não ajuda ninguém a tentar diagnosticar o problema porque os stacktraces não estão gravados.

E os contra-pontos para 1 e 2 são:

  1. você pode gastar tempo ilimitado aperfeiçoando os diagnósticos "user friendly" para uma aplicação, e ainda não ajudar o tipo de usuário que não pode ou não quer entender ...
  2. Também depende de quem é o utilizador típico.

Como você pode ver, isso é muito mais matizado do que "pegar exceções genéricas é uma má prática".

 6
Author: Stephen C, 2018-10-10 03:06:12