É uma prática ruim de pegar Throwable
?
Por exemplo, algo assim:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
Isso é uma má prática ou devemos ser o mais específicos possível?
java
exception-handling
throwable
ktulinho
fonte
fonte
Respostas:
Você precisa ser o mais específico possível. Caso contrário, bugs imprevistos podem se espalhar dessa maneira.
Além disso,
Throwable
cobreError
também e isso geralmente não tem ponto de retorno . Você não quer pegar / lidar com isso, você quer que seu programa morra imediatamente para que você possa corrigi-lo adequadamente.fonte
Esta é uma má ideia. Na verdade, mesmo pegar
Exception
é geralmente uma má ideia. Vamos considerar um exemplo:Agora, digamos que getUserInput () bloqueie por um tempo e outra thread interrompa sua thread da pior maneira possível (ela chama thread.stop ()). Seu bloco catch irá pegar um
ThreadDeath
erro. Isso é muito ruim. O comportamento do seu código após capturar essa exceção é amplamente indefinido.Um problema semelhante ocorre com a captura de exceção. Talvez tenha
getUserInput()
falhado devido a uma InterruptException ou uma exceção de permissão negada ao tentar registrar os resultados, ou todos os tipos de outras falhas. Você não tem ideia do que deu errado, por isso também não tem ideia de como consertar o problema.Você tem três opções melhores:
1 - Capture exatamente a (s) exceção (ões) que você sabe como lidar:
2 - Relembre qualquer exceção que você encontrar e não souber como lidar:
3 - Use um bloco finally para que você não precise se lembrar de relançar:
fonte
throw new Exception("Some additional info, eg. userId " + userId, e);
. Isso será registrado em uma boa exceção com 10 causas.Também esteja ciente de que quando você pega
Throwable
, você também pode pegar oInterruptedException
que requer um tratamento especial. Consulte Lidando com InterruptedException para obter mais detalhes.Se você deseja apenas capturar exceções não verificadas, também pode considerar este padrão
Dessa forma, quando você modifica seu código e adiciona uma chamada de método que pode lançar uma exceção verificada, o compilador irá lembrá-lo disso e então você poderá decidir o que fazer neste caso.
fonte
direto do javadoc da classe Error (que recomenda não capturá-los):
fonte
Não é uma prática ruim se você absolutamente não pode ter uma exceção borbulhando de um método.
É uma prática ruim se você realmente não pode lidar com a exceção. Melhor adicionar "throws" à assinatura do método do que apenas pegar e relançar ou, pior, envolvê-lo em uma RuntimeException e relançar.
fonte
Throwable
instâncias - por exemplo, para registro de exceção personalizado.Às vezes, o Catching Throwable é necessário se você estiver usando bibliotecas que geram erros com muito entusiasmo, caso contrário, sua biblioteca pode matar seu aplicativo.
No entanto, seria melhor nessas circunstâncias especificar apenas os erros específicos lançados pela biblioteca, em vez de todos os Throwables.
fonte
Throwable é a classe base para todas as classes que podem ser lançadas (não apenas exceções). Há pouco que você pode fazer se capturar um OutOfMemoryError ou KernelError (consulte Quando capturar java.lang.Error? )
Capturar exceções deve ser o suficiente.
fonte
depende da sua lógica ou para ser mais específico às suas opções / possibilidades. Se houver alguma exceção específica à qual você possa reagir de uma forma significativa, você pode pegá-la primeiro e fazer isso.
Se não houver e você tiver certeza de que fará a mesma coisa para todas as exceções e erros (por exemplo, sair com uma mensagem de erro), então não será problema pegar o que pode ser jogado.
Normalmente, o primeiro caso se mantém e você não pegaria o que pode ser jogado. Mas ainda existem muitos casos em que capturá-lo funciona bem.
fonte
Embora seja descrito como uma prática muito ruim, às vezes você pode encontrar casos raros em que não só é útil, mas também obrigatório. Aqui estão dois exemplos.
Em um aplicativo da web onde você deve mostrar uma página de erro completa significativa para o usuário. Este código garante que isso aconteça, pois é muito grande em
try/catch
torno de todos os seus manipuladores de solicitação (servlets, ações de struts ou qualquer controlador ...)}
Como outro exemplo, considere que você tem uma classe de serviço que atende a negócios de transferência de fundos. Este método retorna um
TransferReceipt
se a transferência foi feita ouNULL
não.Agora, imaginando que você obtenha uma
List
série de transferências de fundos do usuário e você deve usar o serviço acima para fazer todas elas.Mas o que acontecerá se alguma exceção acontecer? Você não deve parar, pois uma transferência pode ter sido bem-sucedida e outra não, você deve continuar com todos os usuários
List
e mostrar o resultado a cada transferência. Então você acaba com este código.Você pode navegar em muitos projetos de código aberto para ver se o
throwable
está realmente armazenado em cache e gerenciado. Por exemplo, aqui está uma pesquisa detomcat
,struts2
eprimefaces
:https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch % 28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
fonte
throwable
, que é sobre o que é esta perguntaA pergunta é um pouco vaga; você está perguntando "está tudo bem em pegar
Throwable
" ou "está tudo bem em pegar umThrowable
e não fazer nada"? Muitas pessoas aqui responderam a última pergunta, mas isso é um problema secundário; 99% do tempo que você não deve "consumir" ou descartar a exceção, se você está pegandoThrowable
ouIOException
ou qualquer outra coisa.Se você propagar a exceção, a resposta (como a resposta a tantas perguntas) é "depende". Depende do que você está fazendo com a exceção - por que você está capturando.
Um bom exemplo de por que você deseja capturar
Throwable
é fornecer algum tipo de limpeza se houver algum erro. Por exemplo, em JDBC, se ocorrer um erro durante uma transação, você deseja reverter a transação:Observe que a exceção não é descartada, mas propagada.
Mas, como regra geral, pegar
Throwable
porque você não tem um motivo e está com preguiça de ver quais exceções específicas estão sendo lançadas é uma forma inadequada e uma má ideia.fonte
De modo geral, você deseja evitar pegar
Error
s, mas posso pensar em (pelo menos) dois casos específicos em que seja apropriado fazer isso:AssertionError
que, de outra forma, são inofensivos.fonte
Se usarmos o que pode ser jogado , ele também cobre o erro e é isso.
Exemplo.
}
Resultado:
fonte
Throwable é a superclasse de todos os erros e exceções. Se você usar Throwable em uma cláusula catch, ele não apenas capturará todas as exceções, mas também todos os erros. Erros são lançados pela JVM para indicar problemas sérios que não devem ser tratados por um aplicativo. Exemplos típicos disso são OutOfMemoryError ou StackOverflowError. Ambos são causados por situações que estão fora do controle do aplicativo e não podem ser tratadas. Portanto, você não deve capturar Throwables a menos que esteja bastante confiante de que será apenas uma exceção dentro do Throwable.
fonte
Embora seja geralmente uma prática ruim capturar Throwable (conforme elucidado pelas inúmeras respostas a esta pergunta), os cenários em que a captura
Throwable
é útil são bastante comuns. Deixe-me explicar um desses casos que uso no meu trabalho, com um exemplo simplificado.Considere um método que realiza a adição de dois números e, após a adição bem-sucedida, envia um alerta por e-mail para certas pessoas. Suponha que o número retornado seja importante e usado pelo método de chamada.
O código para enviar alertas de e-mail lê muitas configurações do sistema e, portanto, pode haver uma variedade de exceções lançadas a partir desse bloco de código. Mas não queremos que nenhuma exceção encontrada durante o despacho do alerta se propague para o método do chamador, já que esse método está simplesmente preocupado com a soma dos dois valores Inteiros que ele fornece. Assim, o código para enviar alertas de e-mail é colocado em um
try-catch
bloco, ondeThrowable
é capturado e quaisquer exceções são meramente registradas, permitindo que o restante do fluxo continue.fonte
Exception
tudo por todos os meios, mas nãoThrowable
.