Exceptions
Exceptions
Exceptions are events that occur within the normal flow of program execution that disrupt the normal flow of control.
Throwing Exceptions
Exceptions can occur when raised by other code we call, but an exception can also be raised manually using a throw statement. Any object that inherits, either directly or indirectly, from the Throwable class, can be raised as an exception.
//pop from a stack
public E pop(){
if(this.size == 0)
throw new EmptyStackException();
//pop the item
}
Exception Handling
- Exceptions can be caught using a
try-catchblock - If any code within the
tryblock raises an exception, thecatchblock will be executedcatchblocks must specify the type of exception to catch- Can have multiple catch blocks for different exceptions
- Only 1 catch block will be executed
- A
finallyblock can be included to add any code to execute after the try-catch, regardless of if an exception is raised or not. - The exception object can be queried through the variable
e
try{
//try to do something
} catch (ExceptionA e){
//if an exception of type ExceptionA is thrown, this is executed
} catch (ExceptionB e){
//if an exception of type ExceptionB is thrown, this is executed
} finally{
//this is always executed
}
Exception Heirachy
- The
Throwableclass is the parent class of all errors and exceptions in Java - There are two subclasses of
ThrowableError, which defines hard errors within the JVM that aren't really recoverableException, which defines errors that may occur within the code- There are two kinds of exception, checked and unchecked

Checked and Unchecked Exceptions
- Checked exceptions must be either caught or re-thrown
IOExceptionis a good example
- When a method that may throw a checked exception is required, there are two options
- Wrap the possibly exception-raising code in a
try-catch - Use the
throwskeyword in the method definition to indicate that the method may throw a checked exception
- Wrap the possibly exception-raising code in a
public static void ReadFile() throws FileNotFoundException{
File f = new File("non-existant-file.txt")
FileInputStream stream = new FileInputStream(f);
}
// OR
public static void ReadFile(){
File f = new File("non-existant-file.txt")
try{
FileInputStream stream = new FileInputStream(f);
} catch (FileNotFoundException){
e.printStackTrace();
return;
}
}
- Unchecked Exceptions all subclass
RunTimeException- ie
NullPointerExceptionandArrayIndexOutOfBoundsException
- ie
- Can be thrown at any point and will cause program to exit if not caught
Custom Exceptions
- Custom exception classes can be created
- Should subclass
Throwable- Ideally the most specific subclass possible
- Subclassing
Exceptiongives a new checked exception - Subclassing
RunTimeExceptiongives a new unchecked exception
- All methods such as
printStackTraceandgetMessageinherited from superclass - Should provide at least one constructor that overrides a superclass constructor
public class IncorrectFileExtensionException
extends RuntimeException {
public IncorrectFileExtensionException(String errorMessage, Throwable err) {
super(errorMessage, err);
}
}
Generics
Generics allow for classes to be parametrised over some type or types, to provide additional compile time static type checking. A simple box class parametrised over some type E, for example:
public class Box<E>{
E item;
public Box(E item){
this.item = item;
}
public E get(){
return item;
}
public E set(E item){
this.item = item;
}
}
Generic Methods
Methods can be generic too, introducing their own type parameters. The parameters introduced in methods are local to that method, not the whole class. As an example, the static method below compares two Pair<K,V> classes to see if they are equal.
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
Type erasure
Type information in generic classes and methods is erased at runtime, with the compiler replacing all instances of the type variable with Object. Object is also what appears in the compiled bytecode. This means that at runtime, any type casting of generic types is unchecked, and can cause runtime exceptions.