Retornar a exceção em java

Eu tenho uma pergunta muito simples sobre re-jogando exceção em Java.

Aqui está o trecho de código:

public static void main(String[] args) throws FileNotFoundException { try { FileReader reader = new FileReader("java.pdf"); } catch (FileNotFoundException ex) { throw ex; } } public static void main(String[] args) throws FileNotFoundException { FileReader reader = new FileReader("java.pdf"); } 

Por que precisamos re-lançar ex na primeira versão enquanto a segunda versão parece mais elegante? Quais podem ser os benefícios e qual versão é preferida à outra?

Você está certo. Segunda versão é melhor. Além disso, a primeira versão não faz qualquer sentido. Ele faz o mesmo, exceto que o rastreamento de pilha da exceção será “errado”.

Existem as seguintes razões para “re-lançar” exceções:

  1. Se você tem algo para fazer antes.
  2. Se você pegar a exceção de um tipo e lançar exceção de outro tipo:

exemplo:

 try { // do something } catch (IOException ioe) { throw new IllegalStateException(ioe); } 

No exemplo dado, o lançamento da Exception não serve para nada.

Isso pode ser útil se o método que captura e, em seguida, lança novamente a exceção, precisa executar alguma ação adicional ao ver a Exception e também deseja que a Exception seja propagada para o chamador, para que o chamador possa ver a Exception e também tome alguma ação.

Eu só iria pegar / relançar uma exceção (em vez de apenas jogá-lo) se eu quisesse fazer outra coisa no bloco catch – por exemplo, escrever uma instrução de log antes de recomeçar.

Além de querer fazer algo com a exceção antes de sair – como a criação de log, a outra vez que você faria algo como isso é se quiser envolvê-lo como uma exceção diferente, como:

 try { FileReader reader = new FileReader("java.pdf"); } catch (FileNotFoundException ex) { throw new ServletException(ex); } 

A questão é por que você acha que precisa retroceder a exceção. Eclipse sugeriu cercar com try-catch ? Na prática, raramente voltamos a exibir a mesma exceção, mas muitas vezes pegamos uma e lançamos outra que envolve a primeira, especialmente se a exceção do invólucro estiver desmarcada. Isso acontece sempre que você tem chamadas declarando exceções verificadas, mas o método em que você escreve essas chamadas não declara essas exceções:

 public int findId(String name) { try { return db.select("select id from person where name=?", name); } catch (SQLException e) { throw new RuntimeException(e); } } 

O stream de execução pára imediatamente após a instrução throw ; quaisquer declarações subseqüentes não são executadas. O bloco try mais próximo é inspecionado para ver se ele possui uma instrução catch que corresponde ao tipo de exceção.

Se encontrar uma correspondência, o controle será transferido para essa instrução. Caso contrário, a próxima instrução de inclusão será inspecionada e assim por diante. Se nenhuma catch correspondente for encontrada, o manipulador de exceção padrão interromperá o programa e imprimirá o rastreamento de pilha.

Se o método for capaz de causar uma exceção que não manipula, deverá especificar esse comportamento para que os responsáveis ​​pela chamada do método possam se proteger contra essa exceção.

Pode-se fazer isso incluindo uma cláusula throws na declaração do método. Uma cláusula throws lista os tipos de exceções que um método pode lançar. Isso é necessário para todas as exceções, exceto as do tipo Error ou RuntimeException , ou qualquer uma de suas subclasss. Todas as outras exceções que um método pode lançar devem ser declaradas na cláusula throws . Se não estiverem, ocorrerá um erro em tempo de compilation.

Ambas as versões produzirão o mesmo stacktrace

sem tentar / pegar

 import java.io.FileNotFoundException; import java.io.FileReader; public class Test { public static void main(String[] args) throws FileNotFoundException { // try { FileReader reader = new FileReader("java.pdf"); // } catch (FileNotFoundException ex) { // throw ex; // } } } 

vai sair

 Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at java.io.FileInputStream.(FileInputStream.java:93) at java.io.FileReader.(FileReader.java:58) at Test.main(Test.java:7) 

com try / catch / throw same exception

 import java.io.FileNotFoundException; import java.io.FileReader; public class Test { public static void main(String[] args) throws FileNotFoundException { try { FileReader reader = new FileReader("java.pdf"); } catch (FileNotFoundException ex) { throw ex; } } } 

irá produzir exatamente o mesmo que antes

 Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at java.io.FileInputStream.(FileInputStream.java:93) at java.io.FileReader.(FileReader.java:58) at Test.main(Test.java:7) 

try / catch / throw wrapping exception

Uma abordagem aconselhável é lançar suas próprias exceções. Enrole a exceção que você acabou de capturar se quiser fornecer detalhes da causa raiz (pode ser desejado ou não desejado)

 import java.io.FileNotFoundException; import java.io.FileReader; public class Test { public static void main(String[] args) { try { FileReader reader = new FileReader("java.pdf"); } catch (FileNotFoundException ex) { throw new RuntimeException("Error while doing my process", ex); } } } 

Você pode ver claramente o problema de nível superior (meu processo não foi concluído) e a causa raiz que levou a ele (arquivo java.pdf não encontrado)

 Exception in thread "main" java.lang.RuntimeException: Error while doing my process at Test.main(Test.java:9) Caused by: java.io.FileNotFoundException: java.pdf (The system cannot find the file specified) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at java.io.FileInputStream.(FileInputStream.java:93) at java.io.FileReader.(FileReader.java:58) at Test.main(Test.java:7)