In any application, errors can occurred at any moment, as developer we need to handle them properly to avoid the application to crash awfully. In Java, exceptions are used to throw errors, beginning be thrown by the system, or the programmers, and the try/catch
block is the alternative to handle those errors properly.
Try and Catch Block
- The
try
statement contains a block of code that will be run “safely” in case an expected error happens.
- The
catch
statement defines a block of code to be executed, if an error occurs in the try block. So, the application can handle that situation and avoid propagating the exception to crash the application.
try{ //Your code that may cause an exception }catch (Exception exception){ //error handling code }
Because during the execution of the try block, we might have more than one different cause of an exception, the try can have more than one catch block.
try{ //Your code that may cause an exception } catch (FileNotFoundException ex){ //Code to handle the File Not Found Exception } catch (IlegalArgumentException ex){ //Code to handle the IlegalArgument Exception } catch (NumberFormatException ex) { //Code to handle the NumberFormatException Exception }
When adding more than one catch block, the order matters! So be sure to add the more specific exceptions first, and finally the more generic exceptions. Otherwise, if a generic exception catch block is declared ay the beginning it will hide the other ones.
try{ //Your code that may cause an exception } catch (Exception ex){ //Code to handle the Exception(parent class of any exception) } catch (IlegalArgumentException ex){ //Hidden by the catch(Exception). It will be never executed. } catch (NumberFormatException ex) { //Hidden by the catch(Exception). It will be never executed. }
Finally Block
A try/catch block can include a finally
block at the end. The purpose of the finally
block is to be always executed when the try
block exits.
It doesn’t matter whether an exception happens or not, nor if a return
, continue
or break
statement is called internally. The finally block is always executed. Even, if an unexpected exception is thrown into the catch block, the finally block will be executed, and the exception then will be propagated.
Note: The only exception to the “always” rule is if the JVM exits while it was running code into a try block. Calling the System.exit
method, or sending a kill signal from the operative system.
The block is very useful to cleanup code after the try block finishes, it could be use to release resources (connections, files). So, it is a good practice to add it even when no exceptions are anticipated.
try{ //Your code that might throw an exception } catch (exception MyException){ //handle the exception here } finally { //Release resources here }
Note: The try block allows having a finally block without catch block, in other words a try/finally block. Therefore, something like: try{//my code} finally {//release resources}
is valid…
Multi-catch Block
As we have seen, the try block allows having more than one catch block. What about if we have multiple exceptions that could be handled in the same way?
For that purpose, the multi catch block can be used.
try{ //Your code that may cause an exception } catch (IOException | SQLException | FileNotFoundException exc){ //Code to handle the IOException or SQLException or FileNotFoundException System.error("The application was not ready because "+exc.getMessage()); } catch (NumberFormatException ex) { //Code to handle the NumberFormatException Exception System.error("The value of xxx is not a number"); }
We can reduce the amount of duplicated code to handle exceptions.
Try With Resources
The try with resources
is another useful feature to replace using the try/catch/finally
block in cases when need to create and use resources during the try block and release them during the finally
block. It that resource implements the Closable
or AutoClosable
interface, the block will call the method close()
automatically when the try finishes.
So, adding manually those calls to the close
method in the finally block is not required anymore.
try (Statement stmt = con.createStatement()) { //using the resource }
It allows to initialize or define more than one resource, all of them separated by a semi-colon ;
. In that case, the resources that were defined/acquired first will be closed last. Also, in Java 9 or newer versions the resources can be initialized before the try, and defined in the try.
final Statement stmt = con.createStatement(); final BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset) try (stmt; writer) { //Your code }
A try-with-resources block can still have the catch and finally blocks, which will work in the same way as with a traditional try block. It’s called “extended try-with-resources”.
try (Statement stmt = con.createStatement(); BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset)) { //Your code } catch (SQLException | IOException ex){ //Handle any error } finally{ System.out.println("Finally is called here!"); }
However, it’s important to know that the “generated” finally which closes the resources will be executed right after the try
and before the “extra catch/finally blocks”. Then, the explicit “catch” or “finally” block will be executed.
all resources will have been closed (or attempted to be closed) by the time the
Java 8 Documentation, Chapter 14, Try Catch, extended try-with-resourcesfinally
block is executed, in keeping with the intent of thefinally
keyword.
References
- https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
- https://beginnersbook.com/2013/04/try-catch-in-java/
- https://www.w3schools.com/java/java_try_catch.asp
- https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
- https://www.baeldung.com/java-try-with-resources
- https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3.2