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.
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 ...
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.
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.
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.
- a tua versão é significativamente mais código. 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:
- 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 ... 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".