dagblog.
← Archive

Declared Runtime Exceptions: The Best of Both Worlds?


Exceptions on the Java platform are familiar enough, but there's no universally agreed way to design an exception system at the application architecture level. TheServerSide recently hosted a discussion about declared runtime exceptions, so let's take a look at the idea here.

The following is based on Declared Unchecked Exception: The Best of Both Worlds, published on the Hacking Architect blog.

The Basics

  • The application exception hierarchy inherits exclusively from java.lang.RuntimeException, so all its exceptions are runtime exceptions by definition.
  • Every application exception is declared in the throws clause of any method that can throw it.
  • Handle ordinary runtime exceptions like java.lang.NullPointerException in the usual way, without the explicit declaration used for application exceptions.
public class MyORMException extends RuntimeException { ... }
public class ObjectNotUniqueException extends MyORMException { ... }
... // define other exceptions
public class MyORMSession {
public void commit() throws ObjectNotUniqueException,
DatabaseException, DataSecurityException;
}
What This Means
Let's see what this approach looks like in code.
  • Even though an exception appears in the throws clause, client code is free to leave it unhandled because it is a runtime exception.
  • Changing the throws clause in the future does not force you to change client code.
  • The method declaration tells us which application exceptions can occur and which ones we might want to handle.

Trade-offs

Of course, this approach also has a downside for our code.
  • We lose static checking. The compiler and the IDE will give no warning about an unhandled exception.
  • We have to keep the throws clauses of the relevant methods up to date ourselves.
Despite its clear benefits, the approach has a few side effects. I wouldn't use it for the entire application exception hierarchy. A hierarchy of declared runtime exceptions suits parts of the system where the exceptions are systemic, such as the database layer. Application logic is a poor fit. Checked exceptions make sense there because the logic itself may require an exceptional situation to be handled explicitly, for example when a transfer between accounts exceeds a limit.
My advice is to use this approach sparingly. If you've adopted it, I'd love to hear about your experience in the comments.

Medium version

Related articles

Related CZ Podcast episodes