Home  Exceptions  try/catch  finally  Throwing  Exception hierarchy  Unchecked exceptions  Exception recasting  Uncaught exceptions

When to recast exceptions

The technique of recasting an exception, typically recasting a checked exception into an unchecked exception, can be an extremely powerful technique. Care should be taken not to overuse recasting when the caller really should expect an exception to occur and be able to handle an exception cleanly. But in the right circumstances, recasting an exception offers various advantages and in some cases is almost necessary.

Recasting from checked to checked

Occasionally, we may recast a checked exception to another type of checked exception. We'd generally do this in cases where detecting, say, an IOException in a particular part of our code indicates a more specific type of error, and we want to signal that fact to the caller. For example, imagine a method that connects to a database, runs some SQL and then closes the connection. Both connecting to a database and running some SQL against it can throw a SQLException. We could catch the SQLException while connecting and recast it to a ConnectionException (an exception class that we create). But when running the SQL, we would leave any SQLException intact. Thus, the caller would easily know what the source of the problem was.

public void connectAndRunSql(String sql) throws SQLException, ConnectionException {
  Connection conn;
  try {
    conn = createConnection();
  } catch (SQLException sqlex) {
    throw new ConnectionException(sqlex);
  }
  // in the remainder of the method, let SQLException be propagated
  try {
    // ... execute SQL on conn ...
  } finally {
    conn.close();
  }
}

Recasting from checked to unchecked

Avoiding exception "fuss"

There are parts of the Java API that are either (a) just too fussy when it comes to exceptions; or (b) an interface or abstract class where it is sensible to throw a checked exception in some cases, but where in others the exception would in practice be massively rare. Examples include:

  • invoking methods via reflection;
  • deserialising objects (when deserialising a String, we have to catch ClassNotFoundException just in case the String class is missing...);
  • calling methods declared to throw InterruptedException;
  • reading/writing to ByteArrayInputStream and ByteArrayOutputStream;
  • my all-time favourite, the DOM XML parsing API1.

For example, let's say we're calling some method that takes an InputStream to read some data:

public void processData(InputStream in) throws IOException {
  ...
}

Because it performs I/O on an InputStream, the method throws IOException. But if we know that in practice, we are passing it a ByteArrayInputStream, then we don't expect the exception to ever be thrown, so might write the following:

ByteArrayInputStream in = ...
try {
  processData(in);
} catch (IOException ioex) {
  throw new RuntimeException("Unexpected I/O error", ioex);
}

When we're "not allowed" to throw an exception

When you override a method (or implement a method from an interface), the overrding method cannot declare new execptions not declared by the method being overridden. In practice, there are some obvious cases where we do need to call methods that can throw exceptions, but don't really expect to deal with them inside our method. A common example is Thread.run(). In such cases, we may choose to recast the exception to a RuntimeException.


1. This is undoubtably one of the worst offenders in forcing the caller to handle a whole raft of stupid checked exceptions at every possible moment. (Does anyone really expect to have to handle a "ParserConfigurationException"...??) Never design an API like this.

comments powered by Disqus

Unless otherwise stated, the Java programming articles and tutorials on this site are written by Neil Coffey. Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Javamex UK 2009. All rights reserved.
Search this site:
Threads Database Profiling Regular expressions Random numbers Compression Exceptions C Equivalents in Java

 What do you think of this article? Did it help you? Found a mistake? Feedback and suggestions here