The Runtime Exceptions vs Checked Exceptions Debate

As with any programming community there are always hotly discussed topics. Some can get pretty heated at times and none more so than one of the topics I'm going to discuss today.

In Java, should we prefer runtime exceptions or checked exceptions? When should we use unchecked exceptions and when checked?

Before we discuss one approach over the other let's understand what checked and unchecked (runtime) exceptions are in the Java world.

Checked Exceptions

Checked exceptions, in my view, are caused by circumstances that we know our app should cater for. Perhaps a file isn't present and we need to provide an alternative such as handling and closing that file and maybe even building a different response in the app as a result (such as reporting a different error message and allowing it to bubble up the call stack). This is a problem or issue we might expect.

Now let's look at a code example.

Let's say for arguments sake we write a service that consumes Google's Places API. It's entirely possible that, when we make an HTTP call to return place details for a particular place id, we may encounter any number of problems such as temporary internet connection issues, problems with Google's API (hard to believe but it sometimes does happen!) or API restrictions imposed by Google themselves such as rate limiting (which we may or may not choose to represent as an exceptional circumstance - we could argue we should never reach a limit).

In this example we have an HTTP client that handles both a checked and unchecked exception:

public class CheckedVsUncheckedHttpClient {

    String key = "<your_google_api_key>";

    String googlePlaceUrl = "https://maps.googleapis.com/maps/api/place/details/json?key=%s&placeid=%s";

    private RestTemplate restTemplate;

    private ObjectMapper mapper = new ObjectMapper();

    public CheckedVsUncheckedHttpClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public GooglePlaceResponse googlePlaceChecked(String placeId) throws ServiceUnavailableException, IOException {
        try {
            String json = restTemplate.getForObject(String.format(googlePlaceUrl, key, placeId), String.class);
            return mapper.readValue(json, GooglePlaceResponse.class);
        } catch (RestClientException ex) {
            throw new ServiceUnavailableException(ex);
        }
    }

    public GooglePlaceResponse googlePlaceUnchecked(String placeId) throws Exception {
        String json = restTemplate.getForObject(String.format(googlePlaceUrl, key, placeId), String.class);
        return mapper.readValue(json, GooglePlaceResponse.class);
    }
}

The googlePlaceChecked method - throws a ServiceUnavailableException and an IOException. ServiceUnavailableException is a checked exception class that we define so that we can wrap multiple exceptions and handle them in a uniform way (one of the big benefits of using checked exceptions).

Our IOException just so happens to be an exception that is thrown if the JSON object that comes back from the Google service doesn't conform to the specification that we expect. We're using the Jackson API, a Java library for processing the JSON into an object.

Now in 99.9% of occasions this will be okay but in that 0.1% of cases when the API specification changes, we fail to bind the JSON to an object, it will throw an IOException. Our application should be built to cover this possible event. In the example, we throw a ServiceFailedException because it's not managed to complete the HTTP request successfully at all and something catastrophic (and non temporary) has happened.

Unchecked Exceptions

Now, looking back at our example, if we handled the exceptions by catching just an Exception and throwing a Throwable (unchecked) exception, then we have little to no control both within this method and any methods above it. We can't make a different decision and we can't possibly know what caused any errors which were caught in the try.

Unchecked exceptions aren't always bad. You can throw an unchecked exception if you don't really care about the exception bubbling up to the top of the call stack and you're not really bothered about handling it. A good example of this would be something catastrophic.

For example, if some data MUST exist in order for an application to function normally and logically then we may want our app to just fail and to tell us why.

In The Java Programming Language by Arnold, Gosling and Holmes unchecked exceptions are described as “conditions that, generally speaking, reflect errors in your program's logic and cannot be reasonably recovered from at run time.“

This perfectly describes the kind of errors I'm talking about - unrecoverable errors.

The Age Old Argument

I've heard many many developers claim that dealing with checked exceptions is a 'hassle' and pointless because often when refactoring you spend a lot of time fixing exception signatures on methods and satisfying the compiler.

However, from my perspective this viewpoint is lazy. Developers as a species, we're a lazy bunch, so I can sympathise with this. However, I can't remember how many times I've had issues in a live application where exceptions that should have been handled properly weren't. So I have

Thankfully, Oracle have also had their say on this debate and agree that checked exceptions are incredibly important to handle and cater for cases where our app can recover.

Before you leave, I'd love to hear your thoughts and war stories on checked vs unchecked exceptions.

Please leave some comments below.

James Murphy

Java dev by day, entrepreneur by night. James has 10+ years experience working with some of the largest UK businesses ranging from the BBC, to The Hut Group finally finding a home at Rentalcars.

Manchester, UK
comments powered by Disqus