Chapter:Exceptions - Creating your own

From Juneday education
Jump to: navigation, search

Meta information about this chapter (short)

Expand using link to the right to see the full content.

Introduction

This chapter shows the students how to write a class which is an exception. Both how to create a new class for a checked exception (by extending java.lang.Exception) and how to create a class which is a new kind of runtime exception (by extending java.lang.RuntimeException).

As a part of this, we show how to create constructors for calling the superclass' constructors.

Purpose

The purpose is to make the students capable of creating new types of exceptions, and also to re-visit how to create constructors and call superclass constructors and how to do some inheritance.

Goal

After this chapter, the student shall understand:

  • How to create a new type of exception
    • Extending Exception to create a new type of checked exception
    • Extending RuntimeException to create a new type of runtime exception (unchecked)
  • How to overload (make more than one version of) the constructors and call the superclass' constructors

Instructions to the teacher

Common problems

It might be confusing to students to understand why they need to create a new kind of exception. The main reason is to create a named condition for a programming error or a contingency. This, of course, gets extra powerful and useful when you catch a checked exception inside a low level module and rethrows it as a runtime exception so that it bubbles up to some higher level module fault barrier.

Another situation is when you want to hide low level decisions from high level modules, like catching an SQLException and rethrowing it as a StorageException, so that higher level modules don't have to know about the use of a database (and don't have to import e.g. java.sql.SQLException which couples the high level class with a low level class and design decision.

This may prove to be hard to convey to the students.

Exceptions: Creating your own Exception using extends

As always, start by creating a new directory for these exercises. Don't do all your exercises in e.g. your home directory or some other inappropriate place. Always start from scratch with a new directory.

It is possible to create our own custom exception classes using inheritance. We have basically two options when doing this, extend RuntimeException and create an unchecked exception, or extending Exception and create a checked exception. The same reasoning applies to this choice as the one from the previous sections of this chapter. Checked exceptions force the caller of a method to handle-or-declare, while runtime exceptions are unchecked by the compiler (and might thus come more as a surprise for the caller). Review previous sections for a discussion about this.

Simply put, if you think the caller can recover from the situation which caused the exception, then you may use checked exceptions in order to make sure the caller prepares for this event. If you are pretty sure that the caller can't fix the situation anyway, it is possible to go with unchecked exceptions, and hope that there is a global handler which at least lets the application shut down gracefully if it is a really critical problem.

One reason for creating our own custom exceptions, is that we can wrap and hide the actual exception our class might run into. We can still throw an exception when something unwanted happens, but we can wrap it up in an exception which belongs to our package. This way, the client code (callers of our methods) doesn't have to know what the cause exactly is, and this has many benefits. First of all, we hide implementation details from the caller by using only our own exceptions. Second, the caller doesn't have to import the package where the original exception comes from, which is great, because if we change our mind later, then the caller is depending on this decision and might have to import some new exception from some new API, which is bad. Third, we can actually afford to be more specific about the problem if we use our own exceptions. Writing our own exceptions lets us name them in terms of the problem domain of our application, and not the domain of the API which caused the original exception.

Let's say, for instance, that we write a class which fetches objects and offers a method which returns a list of some objects to the caller. If these objects originally comes from a database, we can hide this fact from the callers, so that we can change our mind later. Also, there are quite a few exceptions which can be thrown when working with a database. Here are a few: BatchUpdateException, RowSetWarning, SerialException, SQLClientInfoException, SQLNonTransientException, SQLRecoverableException, SQLTransientException, SQLWarning, SyncFactoryException, SyncProviderException. Then there are of course also subclasses to these exceptions. Now, the caller of our method simply wants a list of objects, and the caller might accept that this at rare occasions doesn't work. But our bet is that the caller isn't so much interested in learning about the various exceptions connected to databases. We can here create our own exceptions with better names which fit better into the terminology of our application.

In order to extend Exception we simply use the extends keyword, as you would when extending any class. It is good if we provide at least two constructors for flexibility of our Exception class, and we can mimic two constructors from the superclass.

We suggest at least the following two constructors for our custom exception (Let's call the exception class OrderSecurityException):

OrderSecurityException class diagram
public class OrderSecurityException extends Exception{
  public OrderSecurityException(String message){
    super(message);
  }
  public OrderSecurityException(String message, Throwable cause){
    super(message, cause);
  }
}

As you see, we call the constructors of the superclass Exception from our constructors, which passes along the parameters to the respective constructor of Exception.

The second constructors allow us to wrap some other Exception, if we'd want to do that.

We have shown you the syntax for wrapping exceptions in previous sections of this chapter and there is no point in repeating it here.

This section is mostly about syntax, so we will not go any deeper into the various choices we have leading up to design decisions for our custom exceptions. This will be covered in books about more advanced programming issues since this is an introductory Java book. This should come as a welcome surprise for you, because within the scope of this book, all you need to know about how to extend Exception (or RuntimeException) is stuff you already have learned from the chapter on inheritance!

The wrapping of another exception is also very uncomplicated business. You just create an exception using the operator new, and give a message parameter (as a String) as the first argument and a reference to the exception object to wrap as the second argument. Invoking a constructor and passing arguments shouldn't be new information either! We have created numerous objects this was so far in the course.

Chapters on the topic of Exceptions

Here are the chapters on the topic of Exceptions, so that you can check your progress:

Videos

English videos

Swedish videos

Obs! Bara en video på svenska (samma innehåll dock som i engelska men lite längre).

Links

Source code

  • Code from presentations and solutions (github)

Further reading

Where to go next

The next page has exercises for this chapter: Exceptions_-_Creating_your_own_-_Exercises

« PreviousBook TOCNext »