Rethrowing Exceptions with More Inclusive Type Checking - Java @ Desk

Monday, August 18, 2014

Rethrowing Exceptions with More Inclusive Type Checking

Rethrowing Exceptions with More Inclusive Type Checking

With Java SE 7, you can throw more precise exception, i.e. you can actually throw an exception type which a try block can throw.

The exception thrown in the catch clause can be different than the one which is declared in the method signature.

Method declaration can throws more precise exception type.


Consider the following example

public static void invalidRethrow() throws Exception {
 try {
  URL url = new URL("invalidurl");
     BufferedReader reader = new BufferedReader(
      new InputStreamReader(url.openStream()));
     String line = reader.readLine();
     SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
     Date date = format.parse(line);
 } catch (Exception e) {
  System.out.println("Caught exception: " + e.getMessage());
  throw e;
 }
} 


This examples's try block could throw either IOException or ParseException.

Suppose you want to specify these exception types in the throws clause of the invalidRethrow method declaration. It would have lead to compilation error because the exception parameter of catch clause is of type Exception. In releases prior to Java 7, you can only specify the exception type Exception in the throws clause of the invalidRethrow method declaration.

However, in Java 7, you can specify the exception types IOException and ParseException in the throws clause in the invalidRethrow method declaration. The Java 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be IOException and ParseException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either IOException or ParseException:

public static void invalidRethrow() throws IOException, ParseException {
 try {
  URL url = new URL("invalidurl");
     BufferedReader reader = new BufferedReader(
      new InputStreamReader(url.openStream()));
     String line = reader.readLine();
     SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
     Date date = format.parse(line);
 } catch (Exception e) {
  System.out.println("Caught exception: " + e.getMessage());
  throw e;
 }
} 


Caught exception: no protocol: invalidurl
java.net.MalformedURLException: no protocol: invalidurl
 at java.net.URL.<init>(URL.java:585)
 at java.net.URL.<init>(URL.java:482)
 at java.net.URL.<init>(URL.java:431)
 at Exception.test.rethrowEx (test.java:61)
 at Exception.test.main(test.java:52)


The compiler verifies that the type of the rethrown exception meets the following conditions:

1. The try block is able to throw it. i.e. catch cannot throw any other exception which is not declared. It will give compilation error Unhandled exception type Exception
2. There are no other preceding catch blocks that can handle it.
3. It is a subtype or supertype of one of the catch clause's exception parameters.



Previously, you cannot throw an exception that is a supertype of one of the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates the error, "unreported exception Exception; must be caught or declared to be thrown" at the statement throw e.

The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowEx() method declaration.

However, the type of the catch parameter e is Exception, which is a supertype, not a subtype, of IOException and ParseException.

Note: You can use multi-catch here too in the catch clause to be more precise.

public static void rethrowEx() throws IOException, ParseException{
 try {
  URL url = new URL("invalidurl");
     BufferedReader reader = new BufferedReader(
      new InputStreamReader(url.openStream()));
     String line = reader.readLine();
     SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
     Date date = format.parse(line);
 } catch (IOException | ParseException e) {
  System.out.println("Caught exception: " + e.getMessage());
  throw e;
 }
}


The exception handling changes in Java SE 7 allows you not only to write more crisp code by using its multi-catch feature but also allows you to let your bubble up your original exception by allowing you to re-throw it.

This post is written by Dipika Mulchandani. She is a freelance writer, loves to explore latest features in Java technology.





No comments:

Post a Comment