Interesting Java 7 feature – Handle multiple exceptions together and Improved type checking

This article is second in the series of Interesting Java 7 features. If you want to visit the previous article of “try-with-resources” follow the below link-

try-with-resources statement

Handle multiple exceptions together

Since the time, we started writing exception handling in Java code, we had two options – either catch individual exceptions and handle them separately OR catch “Exception” object itself which would implicitly catch all sorts of possible exceptions thrown by the code and then handle it all together.  

Option 1 – Catch multiple exceptions and handle them separately

 

Option 2 – Call Exception in one single block and handle all sort of possible exception in similar way

 public void makeDBCall() {      Connection conn = null;      Statement stmt = null;      ResultSet rs = null;        try {          // JDBC driver          Class.forName("oracle.jdbc.OracleDriver");          // Get connection          conn = DriverManager.getConnection(CONN_STRING, USER, PASSWORD);                  stmt = conn.createStatement();          String sql = "select id, firstName, lastName from Customer";          rs = stmt.executeQuery(sql);          while (rs.next()) {              System.out.println(rs.getInt("Id"));              System.out.println(rs.getString("firstName"));              System.out.println(rs.getString("lastName"));          }      } catch (Exception e) {          e.printStackTrace();      }   }

 

If you see both these options are not ideal. In option 1, we are pretty much doing the same things  in multiple catch blocks but we are required to write code separately. In option 2, there are some side effects of catch Exception because unexpected exceptions in this case (other than ClassNotFoundException and SQLException) would also get caught here which is not the intention.

Java 7 approach –

With Java 7, you can catch multiple exceptions in same catch block and threat them together. This way you don’t need to write the same code again and again (if you want to treat them in similar fashion). One thing to note here is that “e” of type “ClassNotFoundException|SQLException” is final and can’t be re-initialized.

 public void makeDBCall() {      Connection conn = null;      Statement stmt = null;      ResultSet rs = null;        try {          // JDBC driver          Class.forName("oracle.jdbc.OracleDriver");          // Get connection          conn = DriverManager.getConnection("jdbc:oracle:thin:@//localhost:1521/xe", USER, PASSWORD);          stmt = conn.createStatement();          String sql = "select id, firstName, lastName from Customer";          rs = stmt.executeQuery(sql);          while (rs.next()) {              System.out.println(rs.getInt("Id"));              System.out.println(rs.getString("firstName"));              System.out.println(rs.getString("lastName"));          }      } catch (ClassNotFoundException|SQLException e) {              e.printStackTrace();      }

 

What if you want to catch all the exceptions and re-throw the checked exceptions?

There is another interesting feature in Java 7 which enhances the way exceptions are caught and re-thrown. In the similar makeDBCall() example we took earlier, if we need to catch “Exception” and re-throw that, we would be required to add throws in the method signature and caller would need to handle exception too.

Prior to Java 7– In below example, makeDBCall method, two checked exceptions can happen – “ClassNotFoundException” and “SQLException”. But given that we are catching Exception and throwing that, we need to add “throws Exception” in the method signature and caller needs to catch (or possibly rethrow further) that too.

   public void caller() {      try {          makeDBCall();      } catch (Exception e) {          System.out.println("Exception needs to be caught here..No other way");        }  }    public void makeDBCall() throws Exception {      Connection conn = null;      Statement stmt = null;      ResultSet rs = null;        try {          // JDBC driver          Class.forName("oracle.jdbc.OracleDriver"); //can throw ClassNotFoundException          // Get connection          conn = DriverManager.getConnection("jdbc:oracle:thin:@//localhost:1521/xe", USER, PASSWORD);          stmt = conn.createStatement(); // can throw SQLException          String sql = "select id, firstName, lastName from Customer";          rs = stmt.executeQuery(sql);          while (rs.next()) {              System.out.println(rs.getInt("Id"));              System.out.println(rs.getString("firstName"));              System.out.println(rs.getString("lastName"));          }      } catch (Exception e) {              e.printStackTrace();              throw e;      }
 }

 

In Java 7 or later releases – In the same example as above, we can be more explicit and specify “ClassNotFoundException” and “SQLException” (even though we are catching Exception and re-throwing that). In this case caller doesn’t need to handle Exception object and just be worried about these 2 checked exceptions.

Note- This has been possible because we are not modifying the exception object in catch and compiler checks that it’s final and we can just throw checked exceptions in the method signature. If we modify the exception object in catch block, below code won’t compile.

 public void caller() {      try {          makeDBCall();      } catch (ClassNotFoundException | SQLException e) {          System.out.println("Checked Exceptions can be caught here..");        }  }    public void makeDBCall() throws ClassNotFoundException, SQLException {      Connection conn = null;      Statement stmt = null;      ResultSet rs = null;        try {          // JDBC driver          Class.forName("oracle.jdbc.OracleDriver");          // Get connection          conn = DriverManager.getConnection(CONN_STRING, USER, PASSWORD);          stmt = conn.createStatement();          String sql = "select id, firstName, lastName from Customer";          rs = stmt.executeQuery(sql);          while (rs.next()) {              System.out.println(rs.getInt("Id"));              System.out.println(rs.getString("firstName"));              System.out.println(rs.getString("lastName"));          }      } catch (Exception e) {              e.printStackTrace();              throw e;      }
 }

 

 

 


Leave a Reply

Your email address will not be published. Required fields are marked *