Exceptional Java – Thoughts on Java exceptions

Dealing with exceptions is hard. For a while now in the Java world there are two camps. One considers the initial design of the Java exceptions system a sensible one, a feature that contributed greatly to Java’s success. A new camp has also formed in Java world and this new camp considers the original design fundamentally flawed and in dire need of rework. The contention point is the worthiness of checked exceptions. One group considers them essential while the other sees them worthless and even dangerous. This later group wants all exceptions in Java to be unchecked.
I happen to see the value of both types of exceptions so I fall in the first category. After working more than 10 years with Java I consider checked exceptions an essential feature of the language. In this post and a few that will follow I will try to put order in my thoughts about Java exceptions and to answer a number of questions about them, questions like these:

  • How the exception system works in Java and what is its value?
  • What are different types of exceptions for?
  • Is there any value in checked exceptions? Do they impact quality? Do they impact productivity?
  • Who likes checked exceptions?
  • Who hates checked exceptions?
  • How to use exceptions?
  • How not to use exceptions?
  • When to throw exceptions?
  • What to catch and where and what to do with caught exceptions.
  • How to avoid consuming exceptions by accident
  • What is a sensible approach to exceptions in an API?
  • What is a sensible approach to exceptions in an application?
  • What is less than perfect in Java exceptions.
  • How much is the weight of the education factor?
  • Special situations: exceptions in catch blocks and in finally blocks and how to deal with them.


About exceptions in Java and their value for programmers

public void someMethod(int parameter) throws DomainException1
{
    if (parameter < 0)
    {
        // runtime exception
        throw new IllegalArgumentException("negative parameter");
    }
   
    // some code
    ...
   
    try
    {
        // code to try
        ...
    }
    catch (LowLevelException e)
    {
        // treat the exceptional situation right here or
        // re-throw as DomainException1, one of its subclasses or as runtime exception
        ...
    }
    catch (DomainException2 e)
    {
        // treat the exceptional situation right here or
        // re-throw as DomainException1, one of its subclasses or as runtime exception
        ...
    }
    finally
    {
        // code to always execute
        ...
    }
   
    // some code
    ...
   
    if (some condition)
    {
        // checked exception declared above
        throw new DomainException1("bad condition");
    }
   
    // some more code
    ...
}

The code sample above sums most of the common usage and knowledge about Java exceptions. Exceptions are a very interesting and useful concept. Also they are often misunderstood and poorly used by an important percentage of the programmers. While at first sight the concept behind the exceptions seems obvious and their usage trivial, many software writers will tell you that this is not the case. Exceptions are not a new concept but Java was one of the first languages to force programmers to treat them through checked exceptions. The idea behind this design decision in the language has its roots exactly in the complexity of the concept and in the complexity of the decisions related to exceptions.
If we analyze the code above we can see how exceptions and handling exceptions seem to make the code a lot more complex. The emphasis falls on “seems”. MagicThe fact that one has to handle exceptions in Java is not what makes the code more complex. If a problem is complex and potentially can run into exceptional situations then the solution will have to deal with those situations one way or another. In general there is no simple solution for a complicated and complex problem. In the case of a complex problem a simple solution is just wrong or incomplete.

Every time an exception is handled a new execution path is apparently created in the code. But what a programmer has to realize is the fact that regardless of the decision of handling the exception, if the exception occurrence is possible, then a new execution path is already present. And it is always better to be able to decide what to do in that case instead of leaving it to chance. What Java did was to give to programmers a tool, a framework, to help us handle exceptional situations and to help us think in an organized way about exceptional situations. But this doesn’t make the problem less complex. It just provides the means for a more sophisticated solution. The complexity is still there and it needs being dealt with.

So in the code above we can see some of the exception tools provided by Java:

- We can tell the world that one method can encounter an exceptional situation and that whoever calls the method will have to deal with it. This happens on the method declaration line. In this case the method “throws” an instance of an exception class, “DomainException1″. If the creator of the exception class decided that “DomainException1″ is a checked exception, then the caller of this method will have to deal with it in a try/catch block or will have to re-throw it by that declaring it doesn’t know how or it decided not to treat the exception itself.

- We can check for conditions, for example documented (ideally) conditions about parameters and we can refuse such a parameter by throwing an exception. In the sample code an unchecked exception is thrown. Unchecked exceptions don’t need to be declared with “throws” clauses and they don’t force the caller to deal with them in any way. Java provides a default procedure for handling such exceptions and this results in the end in the death of the thread if no method on the stack deals with the exception.

- Java forces us to deal with exceptional situations when the code we call declares it can cause them. When we receive and exception we can decide to deal with it right there on the spot and then continue with the program logic, or we can just re-throw the exception after we did something useful like logging or nothing with it. We can even decide to wrap the exception into a brand new one of a different type or just create a new one, and then throw it again. We also have a way to execute some code no matter if an exceptional situation occurred or not. This is done in the “finally” block and it is a great way of disposing of opened resources.

- At any point in the code we can declare that we are no happy with the execution status and throw a new exception so the world can deal with the situation. An of course we can, and we all should do it, embed useful information into the exception instance, just to allow the caller to make an educated decision on how to handle the exception.

It is obvious from this example that the two important concepts in Java exceptions system are on one hand the exceptions themselves and on the other hand the mechanisms provided by the language for creating, raising (throwing) and handling (catching) an exception.

Next time I will write more about how exceptions are handled. Until then take a look at the top of the exceptions class hierarchy. Does it seem right?

- Throwable (checked)
    - Error (unchecked)
    - Exception (checked)
        - checked hierarchy
            - ...
        - RuntimeException (unchecked)
            - unchecked hierarchy
                - ...

This post is part of a series on exceptions:

  1. Thoughts on Java exceptions
  2. Some exceptions are more equal than others
  3. Less than perfect exceptions hierarchy
  4. Checked exceptions are priceless… For everything else there is the RuntimeException
  5. Design the failure case – Part 1
  6. Design the failure case – Part 2
  7. Exception design relativity
  8. Bad advice on exceptions from Joel

12 thoughts on “Exceptional Java – Thoughts on Java exceptions”

  1. Hello Daniel,

    very good points, thank you for the article. I, myself, came from Delphi and changed to Java. Delphi has no checked exceptions and in Java I hated them right away.

    Today I don’t want to miss them. I wrote about exceptions in general here (http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html) and here (http://goit-postal.blogspot.com/2007/01/how-to-successful-log-in-programming.html). Have a look and enjoy!

    Just my 0,02$, Georgi

  2. I’ve thought recently that there should be a new JSR to move the general checked exceptions in Java to runtime exceptions. This is is because checked exceptions really should be Domain exceptions (InsufficientFundsException, CustomerNotFoundException, NoInventoryInStockException etc).

    SQLException, IOException etc are really almost always runtime exceptions anyway and are the main pain-point IMO for checked exceptions in Java. These tend to need to be caught/tranlated/rethrown over and over again. And tend to pollute our domain objects.

    What do you think?

  3. Hello David,

    I fully agree with Joshua Bloch and the “Effective Java” guidelines. Thanks for the link to your post. It is full of interesting links and it gives me more to think of. I guess the projects one works on and the previous experience influence one’s way of thinking. I tend to think a lot about the exception handling policy in my code even if the code is not an API. In my experience big projects tend to blur the API vs application border. I don’t know who is going to maintain my application 5-10 years from now so I tend to be as rigorous as an API designer. I also don’t know how the code will be used in the future. Somebody might decide to reuse parts of my code to build other applications. I might need to integrate my code with code from some other project and so on.
    The danger I see with an “all unchecked” decision is in the human nature. People tend to not read documentation. Sometimes it is because of the pressure and constraints and sometimes it is because people are lazy :). One thing I don’t like in Java Exceptions is not the checked vs unchecked concepts but the class hierarchy. I don’t see why there is no CheckedException class somewhere towards the top of the hierarchy.

  4. Hi Dan,

    I agree that checked exceptions are domain exceptions. But the domain changes with code level. For low level code that deals with files IOException is a domain exception. For code that deals with a database SQLException is a domain exception. In my opinion if I try to read from a file and the file is not there I should get a checked exception because this situation can be recoverable. True, sometimes it isn’t. But most of the time it is or it should be. I don’t want my thread to die because some pressured programmer forgot to deal with an exception because the compiler didn’t force him to do so. I honestly believe Java is one of the most popular and productive languages because of checked exceptions. Because it takes into account the reality of a very constrained software industry (deadlines anybody?) and the reality of human nature (I don’t do what I am not forced to do).
    I fully agree that checked exceptions are abused and sometimes because of poorly designed APIs they are a pain to deal with (just look at the reflection APIs). But I think unchecked exceptions can be abused as well and, in my opinion, their abuse is even more dangerous.
    I actually think the answer is in education. Senior programmers leading projects should take the time to think about the exception handling policy in their projects and then take the time to educate younger programmers working for them.
    I tend to try to deal with an exception as early as possible at the point where I can make an educated decision if I can recover or not. Also in APIs, internal or external, I present only domain exceptions (LoginFailedException) with lower level exceptions embedded as causes. this way the caller of my API can decide what to do and at what level to look into the problem. I can imagine a piece of code that fails and ends if the login failed while other piece of code might decide to try to login into another repository – unrecoverable vs recoverable…

  5. @Dan Howard: the domain-specific exceptions you list seems to me like things that shouldn’t cause exceptions — e.g., checking for sufficient funds, if a customer exists, or if there’s inventory in stock would be part of the normal logic flow, not “exceptional” conditions.

    On the other hand, an IOException or SQLException serves to flag an imperfectly-reliable interface: if these exceptions are thrown, it may well indicate NOT a coding error, but an “exceptional” condition (i.e., network issues) that can be handled locally, such as putting the task into a queue to be resolved when the resource is available again.

    That seems like the exact definition for where we’d want a checked exception… the “exceptional” situation is quite possibly arising due to outside factors, not due to a coding bug or memory overflow, etc. that cannot be recovered from safely (these kinds of things should be unchecked exceptions).

  6. @Rob Whelan

    This shows how different developers interpret how checked exceptions should be used. ;)

    Checked exceptions were supposed to replace the notion of returning error codes.

    e.g.
    #define INSUFFICIENT_FUNDS -1
    #define NO_INVENTORY -2

    if (account.noMoney()) {
    return INSUFFICIENT_FUNDS;
    }

    if (product.noInventory()) {
    return NO_INVENTORY;
    }

    The C world uses this construct which the Java designers considered bad OOP style.

    So I guess this all depends on how you think checked exceptions should be used.

    @Daniel Pietraru
    Remember that RuntimeException can also be caught if required and can be mentioned in your throws clause.

    My feeling is just that IO and SQL are generally not recoverable in most cases.

  7. @Georgi
    @David Castañeda

    Thank you for the links. I will get to them as soon as possible :)

    @Dan Howard

    Yes I know :). My point is that I prefer checked exceptions because they force me to think about dealing with them earlier than later. Even if I get into an unrecoverable situation I still need to do something about it. Maybe I need to free resources and then I still need a try/finally block.
    On the other hand I strongly believe the personality type influences one’s preferences.

  8. People catch exceptions too much and use finally too little.

    I/O Exceptions often are recoverable, because they involve transient network failures.

    Java contributed a lot of great things, but Checked Exceptions have been absolute disaster, since they’ve contributed to exception phobia in programmers who’ve cut their teeth on Java… They bring bad habits to other languages that don’t have them. See

    http://gen5.info/q/2008/07/31/stop-catching-exceptions/

  9. Good answer, I am looking for the solution of the same question. Find the movies or mp3 you are looking for at my-dvdrip.com the most comprehensive source for free-to-try files downloads on the Web

Comments are closed.