Error Handling with Exceptions




Reading Assignment: Read 17.1-17.7 in Liang
Exercise: 17.3 in Liang




Review Question: What is generalization? What is abstraction?




What is an exception?



No matter what, mistakes happen
...

Ex: User enters the wrong input.
Ex: Programmer forgets to guard against an unexpected input value that crashes the program when it is run.
Ex: Input file does not exist.
Ex: out of bounds array index


... So...
Include code in programs to handle errors like these by writing exception handlers.


In Java, the exception handling approach separates normal code from error handling code in a program.

Exception handling is used when the system can recover from the problem. Recovery procedure = exception handler



Approach of exceptions:
1. The method in which the error occurs handles the problem.
2. The method in which the error occurs doesn't have enough information to fix the problem, so it hands the problem over to a higher context, the calling method.




Exception Handling: Language Features



Try Catch Blocks

"Try" to execute a step in a program and "catch" an exception if it occurs. (Approach 1)


Throw Statement

The throw statement creates an instance of class Exception or a subclass of Exception (like IOException). (Approach 2)




Example: Account class




The Exception Hierarchy


In Java, an exception object = instance of a specialization of the Throwable class


Exception constructors:
Exception()
    - constructs an Exception with no specified detail message

Exception(String s)
    - constructs an Exception with detail message s



Two distinct kinds of exceptions:
1. Exceptions that derive from RuntimeException
             -RuntimeExceptions are thrown by the JVM.
2. Those that do not


General Rule:
A Runtime Exception occurs because you made a programming error.
Other types of exceptions occur because something bad (like an I/O error) happened to your perfectly nice program.


Some exceptions that inherit from RuntimeException
1. A bad cast
2. An out-of-bounds array access
3. A null pointer access


Exceptions that do not inherit from RuntimeException:
1. Trying to open a malformed URL
2. Trying to read from a nonexistent input file


Methods inherited from Throwable:
String getMessage()
    returns the error message string of this throwable object

void printStackTrace()
    prints this Throwable and its backtrace to the standard error stream

void printStackTrace(PrintWriter s)
    prints the Throwable object and its backtrace to specified PrintWriter

String toString()
    returns short description of throwable object


Examples with Exceptions



Exercise: Add:
                       e.printStackTrace(System.out);
to the catch block in the Account class.


Note that now the output indicates which method calls resulted in the exception:
Negative credit: -10 is not allowed
java.lang.Exception
                   at Account.credit (Account.java: 17)
                   at TestAccount.main (TestAccount.java: 22)



Two choices for dealing with exceptions:
1. Advertise the exceptions a method throws (if the method doesn't catch the exception)

2. Catch (i.e. handle) the exception in the method


Ex: Header for readLine() method in class BufferedReader:
public String readLine() throws IOException



Throwing an Exception


Example:
Alternate version of Account class

public class Account
{
 ...
    // The credit method header specifies that it may throw an exception
    public void credit(long amount) throws RuntimeException
    {
         if(amount < 0)
             throw new RuntimeException("Negative credit: " + amount + "is not allowed.");
         setBalance(getBalance() + amount);
    }
    // Since the Exception is not caught, the program will terminate after throwing the exception and printing the stack trace.



When to advertise that your method throws an Exception:
AND your method does NOT handle the exception.


In these situations, you are leaving it to the calling method to fix the problem.




SUMMARY


1. Throwing an Exception:


Ex: String readInfo(BufferedReader in) throws EOFException
{
...
   if(n < len) // file is shorter than expected
       throw new EOFException();
...
}



2. Catching Exceptions:
try
{
    // code that may contain throw statements
}
catch (ExceptionType e)
{
    // handler for this type of exception
}

How this code is executed:
If any of the code in the try block throws an exception of the type specified in the catch clause, then

If none of the code in the try block throws an exception, then the program skips the catch block.


Question: Should you handle an exception or pass it on to the calling method?
Answer: Catch exceptions that you know how to handle. Pass on the ones you don't know how to handle (and add a throws modifier to the method header).


Exercise:  The PrintEm class




Catching Multiple Exceptions




myReturnType  myMethod(...)
{

   try
   {
       // code that might throw exceptions
   }
   catch(MalformedURLException e1)
   {
       // handler for malformed URLs
    }
    catch(IOException e2)
    {
       //handler for I/O errors
    }
}



Finally Clause


When your code throws an exception and doesn't handle it, it stops processing the remaining code in your method. If you have code that needs to be executed whether or not an exception is caught, use the finally clause.

Example:
String msgThatMustBePrinted = "vital message: ...";
try
{
    // code that might throw exceptions
}
catch(IOException e)
{
   // IO problems handled here
}
finally
{
    System.out.println(msgThatMustBePrinted);
}


The program will print the message under all circumstances.


Three situations in which the program will execute the finally clause:
  1. Code throws no exceptions. Program executes all code in try block, then the finally clause code, and then the 1st line after try/catch block.
  2. Code throws an exception that is caught in a catch clause (e.g. IOException). So program executes all code in try block up to point at which exception is thrown - the remaining code in try block is skipped. Program executes code in matching catch clause, and code in finally clause is executed.
  3. Code throws an exception that is not caught by any catch clause. So program executes all code in try block until exception is thrown. Then the remaining code in the try block is skipped. Code in finally clause is executed, and exception is thrown back to calling method.

Examples: Circle classes