Diferença entre Try-Finalmente e Try-Catch
-
27-09-2019 - |
Pergunta
Qual é a diferença entre
try {
fooBar();
} finally {
barFoo();
}
e
try {
fooBar();
} catch(Throwable throwable) {
barFoo(throwable); // Does something with throwable, logs it, or handles it.
}
Eu gosto mais da segunda versão porque me dá acesso ao jogável. Existe alguma diferença lógica ou uma convenção preferida entre as duas variações?
Além disso, existe uma maneira de acessar a exceção da cláusula finalmente?
Solução
Estas são duas coisas diferentes:
- O bloco de captura é executado apenas se uma exceção for lançada no bloco de tentativas.
- O bloco finalmente é executado sempre após o bloco de tentativa (--t-capat), se uma exceção for lançada ou não.
No seu exemplo, você não mostrou a terceira construção possível:
try {
// try to execute this statements...
}
catch( SpecificException e ) {
// if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
// if a more general exception was thrown, handle it here
}
finally {
// here you can clean things up afterwards
}
E, como @Codeca diz em seu comentário, não há como acessar a exceção dentro do bloco finalmente, porque o bloco finalmente é executado mesmo que não haja exceção.
É claro que você pode declarar uma variável que mantém a exceção fora do seu bloco e atribui um valor dentro do bloco de captura. Depois, você pode acessar essa variável dentro do seu bloco finalmente.
Throwable throwable = null;
try {
// do some stuff
}
catch( Throwable e ) {
throwable = e;
}
finally {
if( throwable != null ) {
// handle it
}
}
Outras dicas
Essas não são variações, são coisas fundamentalmente diferentes. finally
É executado sempre, catch
Somente quando ocorre uma exceção.
Finalmente e os blocos de captura são bem diferentes:
- Dentro do bloco de captura, você pode responder à exceção jogada. Este bloco é executado apenas se houver uma exceção não tratada e o tipo corresponde a um ou é subclasse do especificado no parâmetro do bloco de captura.
- Finalmente será sempre executado Depois de experimentar, capturar blocos, se há uma exceção levantada ou não.
Então
try {
//some code
}
catch (ExceptionA) {
// Only gets executed if ExceptionA
// was thrown in try block
}
catch (ExceptionB) {
// Only executed if ExceptionB was thrown in try
// and not handled by first catch block
}
é diferente de
try {
//some code
}
finally {
// Gets executed whether or not
// an exception was thrown in try block
}
significativamente.
Se você definir um bloco de tentativa, você terá que definir
- um finalmente bloco, ou
- um ou mais blocos de captura, ou
- um ou mais blocos de captura e um finalmente bloco
Portanto, o código a seguir também seria válido:
try {
//some code
}
catch (ExceptionA) {
// Only gets executed if
// ExceptionA was thrown in try block
}
catch (ExceptionB) {
// Only executed if ExceptionB was thrown in
// try and not handled by first catch block
}
//even more catch blocks
finally {
// Gets executed whether or not an
// exception was thrown in try block
}
try {
statements;
} catch (exceptionType1 e1) { // one or multiple
statements;
} catch (exceptionType2 e2) {
statements;
}
...
} finally { // one or none
statements;
}
- Todas as declarações de tentativa devem incluir uma cláusula de captura ou uma cláusula finalmente
- Pode ter uma cláusula de captura múltipla, mas apenas uma cláusula finalmente
- Durante qualquer execução, se ocorrer algum erro, o controle será transferido para o bloco de captura apropriado e executa as instruções e, finalmente, o bloco é executado.
Não importa o que o bloco finalmente seja executado, portanto, em geral, finalmente é usado o bloco, quando você tem sessões, conexões de banco de dados ou arquivos ou soquetes estão abertos, o código para fechar essas conexões será colocado. Isso é apenas para garantir que, em um aplicativo, não haja vazamentos de memória ou outros problemas não devem ocorrer.
Finalmente e os blocos de captura são bem diferentes:
Dentro do bloco de captura, você pode responder à exceção jogada. Esse bloco é executado apenas se houver uma exceção não atendida e o tipo corresponder a um ou subclasse do especificado no parâmetro do bloco de captura. Finalmente, será sempre executado após a tentativa de obter blocos, se houver uma exceção levantada ou não.
Tente é usado para executar um método que pode lançar uma exceção
A captura é usada para "pegar" parar essa exceção
finalmente é usado para qualquer limpeza necessária a partir dessa exceção sendo pega ou não
try{
myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
myObject = null; // clean up needed from that exception being caught
}
Na minha pesquisa, finalmente é executado o bloco de pesquisa e é "usado principalmente para as conexões abertas para fechar" e destruir algo que está sendo executado desnecessariamente.
Finalmente, o bloco é sempre executado. O bloco de captura é executado apenas quando uma exceção que corresponde ao parâmetro Blocks é capturada.
Mesmo na primeira forma, você pode registrá -lo no método de chamada. Portanto, não há grande vantagem, a menos que você queira fazer um manuseio especial ali.
Geralmente, quando usamos recursos como fluxos, conexões etc. Temos que fechá -los explicitamente usando o bloqueio finalmente. No programa fornecido abaixo, estamos lendo dados de um arquivo usando o FileReader e estamos fechando -os usando finalmente o bloco.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ReadData_Demo {
public static void main(String args[]){
FileReader fr=null;
try{
File file=new File("file.txt");
fr = new FileReader(file); char [] a = new char[50];
fr.read(a); // reads the content to the array
for(char c : a)
System.out.print(c); //prints the characters one by one
}catch(IOException e){
e.printStackTrace();
}
finally{
try{
fr.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
}
Talvez outros caras como eu procurassem algo assim.
Informações desta página Tutpoint
O Bloco de Tente realizará as declarações que aumentarão a exceção. O bloco de captura manterá a referência lançada do bloco de tentativa e as mensagens necessárias são geradas a partir do bloco de captura. Finalmente, o bloco também é usado para fechar os recursos usados, como fechamento de IO, fechamento de arquivos, fechamento de db. Em Java -9, surgiram recursos de tentativa e menos, onde os recursos são declarados fora da tentativa. é mandatório