Monday, May 7, 2012

When should I create a new Exception class


I notice that a number of Java exception classes differ only in the name of the class and do not add any new functionality. Most exceptions for example just seem to override Exception() or Exception(String message) . This goes against the tenets of inheritance ie:- inherit to add new functionality.



What are some good reasons to create a new Exception class?


Source: Tips4all

10 comments:

  1. Exceptions are a special case. In their case, the inheritance is not to add new functionality, but to add new classes of errors. This lets your code catch particular kinds of errors while ignoring others.

    Say you are writing a large project. You have a Data component, and you have a Display component. They can both fail in various ways, and you want to throw exceptions for these failures. The Display component doesn't care about exceptions arising from the Data component, though, and vice versa. If all the classes just threw Exception, there'd be no way to figure out where the exception came from. However, if you subclass Exception with DataException and GraphicsException, even though they don't add new functionality, you can now throw and catch those particular types of exceptions, i.e. a graphics component can catch GraphicsException and not have to deal with data exceptions.

    ReplyDelete
  2. You can catch exceptions by type, and having an exception of a particular type that is otherwise identical to the base Exception class allows you to be precise in your exception handling.

    I would argue that it does add new functionality directly by increasing the specificity of exception handling code.

    ReplyDelete
  3. Use a new exception type when you want to provide error handling for a certain condition. Take a look at java.io.IOException and you will see the following subclasses:

    ChangedCharSetException
    CharacterCodingException
    CharConversionException
    ClosedChannelException
    EOFException
    FileLockInterruptionException
    FileNotFoundException
    FilerException
    HttpRetryException
    IIOException
    InterruptedIOException
    InvalidPropertiesFormatException
    JMXProviderException
    JMXServerErrorException
    MalformedURLException
    ObjectStreamException
    ProtocolException
    RemoteException
    SaslException
    SocketException
    SSLException
    SyncFailedException
    UnknownHostException
    UnknownServiceException
    UnsupportedDataTypeException
    UnsupportedEncodingException
    UTFDataFormatException
    ZipException


    Say you want to read from a file, you could get a generic IOException, a FileNotFoundException, and an EOFException. You may want to handle each of those cases differently. If all you had was IOException you would have to do something like look at the error message and then do an if/else statement to figure out what the actual error was so you can display a sensible message to the user. With a hierarchy of exceptions you can deal with those situations much easier.

    ReplyDelete
  4. In this case the functionality that inheritance adds is in regards to the catch statement, which can distinguish by type. Normally distinguishing subclasses by type is considered a bad practice, but exception handling is, well, an exception.

    It definitely leads to odd situations (such as multiple catch statements that have the same logic) as you would expect when things are distinguished by type, but that is a limitation of the language.

    ReplyDelete
  5. I would recommend reading all, or most, of Chapter 9 of Effective Java. Especially Item 60: "Favor the use of standard exceptions" and Item 61: "Throw exceptions appropriate to the abstraction".

    EDIT 1: Or Items 42 and 43 in the first edition.

    ReplyDelete
  6. This renaming occurs to remove ambiguity wrt. the error that has occurred. e.g.

    Foo getFoo() throws FooNotFoundException


    will be explicit in indicating that a Foo cannot be found, as opposed to (what?) some illegal state, or a database connection error or similar, and you can choose to code (or not) for that particular error. If you choose to throw a more generic exception, it's less clear (programatically) what's occurred.

    ReplyDelete
  7. It's bad form to just catch any exception because not only will you not know where it came from, but you may be preventing yourself from handling errors correctly when they happen. If you just catch any type exception and handle it the same generic way, you may be hiding other problems in your software, or even introducing new ones. So, technically speaking, subclassing Exception does add new functionality.

    ReplyDelete
  8. Creating an exception for any type is really dumb. Maybe you should create an exception for different layer (DAO, Service, etc) or different action (create record, duplicate record, etc).

    ReplyDelete
  9. If you need or want to differentiate the particular error situation from other errors in code, then it makes sense to subclass the appropriate exception. You should NOT need to peek at the error message to determine what went wrong - that is for human eyes only.

    Also note, that a properly named exception may be enough for a maintainers eye to deduce what went wrong when having to diagnose a stack trace. A typical example is ArrayOutOfBoundsException.

    ReplyDelete
  10. You add a new exception class when a user of your API might need to catch it conditionally (or, for checked exceptions specify different, specific types in a throws).

    ReplyDelete