20. Exceptions
Exceptions provides a way to logical separate the regular code and what to do in an exceptional situation
They make it easy to propagate the exception up the call stack such that the situation can be managed in a desired place
They also allow for differentiating between exception types and how to deal with them specifically
Java’s Throwable class hierarchy.
20.1. Errors
In Java, there are two classes of throwable objects
A throwable object is one that can be thrown with a
throwstatement
Errors are one of the two throwable classes
Errors are typically for unrecoverable situations
They’re generally very abnormal situations
Typically, these are not to be caught and handled
Errors and regarded as unchecked for the purpose of compile-time checks
To understand why these are not caught, consider Java’s OutOfMemoryError
Gets thrown if the Java Virtual Machine (JVM) cannot allocate enough memory for the creation of a new object
If the JVM runs out of memory, there is nothing the program can do to resolve this situation
20.2. Throwing an Exception
Several methods written so far have thrown exceptions
Below are the
removeandremoveFirstmethods from theArraySortedBagimplementationremovedoes not throw an exception, butremoveFirstwill if trying to remove from an empty bag
121 @Override
122 public boolean remove(T element) {
123 if (!contains(element)) {
124 return false;
125 }
126 int index = find(element);
127 shiftLeft(index);
128 rear--;
129 return true;
130 }
131
132 @Override
133 public T removeFirst() {
134 if (isEmpty()) {
135 throw new NoSuchElementException("Empty bag");
136 }
137 T returnElement = bag[0];
138 shiftLeft(0);
139 rear--;
140 return returnElement;
141 }
The exception being thrown by
removeFirst,NoSuchElementException, is a subclass ofRuntimeExceptionIt is an unchecked exception, so the method does not need to include a
throws NoSuchElementExceptionin the method signature
The motivation for using an exception in
removeFirstis, when removing from an empty bag, what should happen?Perhaps this means some critical error happened and the program must stop immediately
Or maybe the program using the bag can just ignore the exception and carry on
Either way, as the writers of the
ArraySortedBag, it is not possible to know how the user of theArraySortedBagshould address the situationAll that can be done is to throw the exception to inform the user that something exceptional happened
One may wonder why the more general
removedoes not throw an exceptionThis is because
The return type of the general
removeis abooleanfalseis a reasonable value to return to communicate that theremovewas not successful
The expected return value of
removeFirstis typeT— the actual first thing in the bagThere is no obvious explicit way to communicate a failure with the returned value
One could return null or some other special value, but exceptions are a more appropriate tool for this scenario
Ultimately, however, it would not be wrong to have the general
removethrow an exception in this situationIn the end it is a design decision
20.2.1. Messages
Notice the string provided the the exception’s constructors
"Empty bag"
The string is the message the exception provide to give details on the exceptional situation
Consider how an
ArrayIndexOutOfBoundsExceptionprovides details on the index used that caused the exception
20.3. Catching Exceptions
If someone is using the
ArraySortedBagimplementation two years from now, it’s not possible to know what they should do to manage the exceptional situationsThe users of the
ArraySortedBagclass will need to deal with them as they see fitWhat should be done if calling
removeFirston an emptyArraySortedBag?
20.3.1. Ignore
Maybe this doesn’t matter and they don’t even try to catch the exception
If the exception is thrown, their program will crash, but this doesn’t matter to them
1// I know this may throw an exception, but whatever
2bag.remove(element);
Since the exception is not caught here, the exception would be propagated to the calling method
This exception will keep being propagated to the calling methods until it is either
Caught somewhere
The
mainmethod propagates the exception and the program crashes
20.3.2. Stop Immediately
Maybe they need to stop the execution of the code immediately
They are running medical equipment that delivers radiation therapy
1try {
2 bag.remove(element);
3} catch (NoSuchElementException e) {
4 someCleanUpMethod();
5 System.exit(1);
6}
20.3.3. Carry On
Maybe they can catch it, print out the stack trace, and then carry on and ignore the issue
The program keeps the spaceship running, so it better not crash
1try {
2 bag.remove(element);
3} catch (NoSuchElementException e) {
4 System.out.println("Caught an Exception");
5 e.printStackTrace();
6}
20.3.4. Rethrow
Perhaps we want to catch the exception and then rethrow it as something more appropriate for our context
1try {
2 bag.remove(element);
3} catch (NoSuchElementException e) {
4 throw new MySpecificException(e);
5}
20.4. Catching Different Exception Types
It is possible that the code being called may throw different exception types
These can be individually caught and handled accordingly
The general idea is as follows
1try {
2 mayThrowVariousExceptions();
3} catch (SomeExceptionA e) {
4 handleSomeExceptionA();
5} catch (SomeExceptionB e) {
6 handleSomeExceptionB();
7} catch (SomeExceptionC e) {
8 handleSomeExceptionC();
9} finally {
10 codeThatWillAlwaysRun();
11}
With multiple
catchstatements, the exception class hierarchy must be consideredAlways order the
catchstatements from most specific to most generalFor example
IOExceptionandFileNotFoundException
1// This is bad
2try {
3 ...
4} catch (IOException e) {
5 ...
6} catch (FileNotFoundException e) {
7 ...
8}
Since
FileNotFoundExceptionis a subclass ofIOException, if aFileNotFoundExceptionis thrown, the firstcatchstatement will catch itIn this scenario, it would not be possible for the code within the second
catchstatement to ever runThis is easily fixed by switching the order of the
catchstatements
20.4.1. Finally
Sometimes it is necessary to have some code run regardless of if an exception was thrown or which exception was caught
The
finallykeyword is used to specify code to be run no matter what happensEg. Closing files
20.5. For Next Time
Go back and read Chapter 3 Section 5
2 pages