Existe uma maneira elegante de lidar com exceções lançadas em finally
bloco?
Por exemplo:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
Como você evita o try
/ catch
no finally
bloco?
Resource
=>Closeable
?Normalmente, uso um dos
closeQuietly
métodos emorg.apache.commons.io.IOUtils
:fonte
Se estiver usando Java 7 e
resource
implementosAutoClosable
, você pode fazer isso (usando InputStream como exemplo):fonte
Indiscutivelmente um pouco exagerado, mas talvez útil se você estiver deixando as exceções borbulharem e não puder registrar nada de dentro do seu método (por exemplo, porque é uma biblioteca e você prefere deixar o código de chamada lidar com exceções e registro):
ATUALIZAÇÃO: examinei isso um pouco mais e encontrei uma ótima postagem no blog de alguém que claramente pensou sobre isso mais do que eu: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Ele vai um passo além e combina as duas exceções em uma, que eu posso considerar útil em alguns casos.
fonte
ignore
exceçãoA partir do Java 7, você não precisa mais fechar explicitamente os recursos em um bloco finally , em vez de usar a sintaxe try -with-resources. A instrução try-with-resources é uma instrução try que declara um ou mais recursos. Um recurso é um objeto que deve ser fechado após o programa terminar com ele. A instrução try-with-resources garante que cada recurso seja fechado no final da instrução. Qualquer objeto que implemente java.lang.AutoCloseable, que inclui todos os objetos que implementam java.io.Closeable, pode ser usado como um recurso.
Suponha o seguinte código:
Se ocorrer alguma exceção, o método close será chamado em cada um desses três recursos na ordem oposta em que foram criados. Isso significa que o método close seria chamado primeiro para ResultSetm, depois para a instrução e no final para o objeto Connection.
Também é importante saber que todas as exceções que ocorrem quando os métodos de fechamento são chamados automaticamente são suprimidas. Essas exceções suprimidas podem ser recuperadas pelo método getsuppressed () definido na classe Throwable .
Fonte: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
fonte
Ignorar as exceções que ocorrem em um bloco 'finalmente' é geralmente uma má idéia, a menos que se saiba quais serão essas exceções e quais condições elas representarão. No
try/finally
padrão de uso normal , otry
bloco coloca as coisas em um estado que o código externo não espera, e ofinally
bloco restaura o estado dessas coisas para o que o código externo espera. O código externo que captura uma exceção geralmente espera que, apesar da exceção, tudo tenha sido restaurado para umnormal
Estado. Por exemplo, suponha que algum código inicie uma transação e tente adicionar dois registros; o bloco "finalmente" executa uma operação de "reversão se não for confirmada". Um chamador pode estar preparado para a ocorrência de uma exceção durante a execução da segunda operação de "adição" e pode esperar que, se capturar essa exceção, o banco de dados estará no estado em que estava antes de qualquer operação ser tentada. Se, no entanto, ocorrer uma segunda exceção durante o rollback, coisas ruins podem acontecer se o chamador fizer quaisquer suposições sobre o estado do banco de dados. A falha de reversão representa uma grande crise - aquela que não deve ser detectada pelo código que espera uma mera exceção "Falha ao adicionar registro".Minha inclinação pessoal seria ter um método finally para capturar exceções que ocorrem e envolvê-las em uma "CleanupFailedException", reconhecendo que tal falha representa um grande problema e que tal exceção não deve ser detectada levianamente.
fonte
Uma solução, se as duas exceções são duas classes diferentes
Mas às vezes você não pode evitar este segundo try-catch. por exemplo, para fechar um fluxo
fonte
Por que você deseja evitar o bloqueio adicional? Visto que o bloco finally contém operações "normais" que podem lançar uma exceção E você deseja que o bloco finally seja executado completamente, você TEM que capturar as exceções.
Se você não espera que o bloco finally lance uma exceção e você não sabe como lidar com a exceção de qualquer maneira (você apenas descarregaria o rastreamento de pilha), deixe a exceção borbulhar na pilha de chamadas (remova o try-catch do finally quadra).
Se você quiser reduzir a digitação, poderá implementar um bloco try-catch externo "global", que capturará todas as exceções lançadas nos blocos finally:
fonte
Depois de muita consideração, acho o seguinte código o melhor:
Esse código garante o seguinte:
fonte
Se possível, você deve testar para evitar a condição de erro para começar.
Além disso, você provavelmente só deve capturar exceções das quais pode se recuperar; se não conseguir, deixe-as se propagar para o nível superior do seu programa. Se você não puder testar uma condição de erro, terá que cercar seu código com um bloco try catch, como você já fez (embora eu recomende ainda capturar erros esperados específicos).
fonte
Você poderia refatorar isso em outro método ...
fonte
Eu normalmente faço isso:
Justificativa: Se eu terminar o recurso e o único problema que tenho é fechá-lo, não há muito que eu possa fazer a respeito. Também não faz sentido eliminar todo o thread se eu terminar com o recurso de qualquer maneira.
Este é um dos casos em que, pelo menos para mim, é seguro ignorar a exceção verificada.
Até hoje não tive nenhum problema em usar esse idioma.
fonte
Tarefa concluída. Sem testes nulos. Captura única, inclui exceções de aquisição e liberação. É claro que você pode usar o idioma Execute Around e só precisa escrevê-lo uma vez para cada tipo de recurso.
fonte
Mudando
Resource
da melhor resposta paraCloseable
Implementa o Streams
Closeable
Assim você pode reutilizar o método para todos os streamsfonte
Eu encontrei uma situação semelhante em que não poderia usar try com recursos, mas também queria lidar com a exceção vinda do fechamento, não apenas registrar e ignorar como o mecanismo closeQuietly faz. no meu caso, não estou realmente lidando com um fluxo de saída, então a falha no fechamento é de mais interesse do que um simples fluxo.
fonte