5. Exceptions

    • Java uses a form of error-trapping called exception handling

Dealing with Errors

The Classification of Exceptions

    • In Java, an exception object is always an instance of a class derived from Throwable

    • You can create your own exception classes

    • The Error hierarchy describes internal errors and resource exhaustion inside the Java runtime system. You should not throw an object of this type

    • There is little you can do for such errors, beyond notifying the user and trying to terminate the program gracefully

    • When doing Java programming, you focus on the Exception hierarchy, exception that derive from RuntimeException and that do not

    • Exceptions that inherit from RuntimeException include - A bad cast, An out-of-bounds array access, A null pointer access

    • Exceptions that do not inherit from RuntimeException - Trying to read pat the EOF, Trying to open a malformed URL, etc

    • The rule - "if it is a RuntimeException, it was your fault"

    • The Java Language Specification calls any exception that derives from the class Error or the class RuntimeException an unchecked exception

    • All other exceptions are called checked exceptions

Throwable

-> Error

-> Exception

-> IOException

-> Runtime Exception

Advertising the Exceptions that a Method Throws

    • A Java method can throw an exception if it encounters a situation it cannot handle

public String readLine() throws IOException {}

public Image loadImage(String s) throws EOFException, MalformedURLException {}

    • The header indicates this method returns string, but it also has the capacity to go wrong in a special way - by throwing an IOException\

    • The runtime system will begin to search for an exception handler that knows how to deal with IOException object

    • If either of below two scenario occurs, you must tell the consumer of the method that there is the possibility of an exception

    • You can call method that throws a checked exception, for example any IO exception

    • You detect an error and throw a checked exception with the throw statement

    • You code should handle unchecked exceptions

    • In summary, a method must declare all the checked exceptions that it might throw

    • You could also catch all exceptions, and no throws specification is necessary

How to Throw an Exception

    • Find an appropriate exception class

    • Make an object of that class

    • Throw it

String readData(BufferedReader in) throws EOFException {

...

throw new EOFException();

}

Creating Exception Classes

    • Create your own exception class from Exception or its subclass

    • It is customary to give both a default constructor and a constructor that contains a detailed message

class FileFormatException extends IOException {

public FileFormatException() {}

public FileFormatException (String gripe) {super(gripe);}

}

String readData(BufferedReader in) throws FileFormatException {

...

throw new FileFormatException ();

}

Catching Exceptions

If any of the code inside the try block throws an exception of the class specified in the catch clause

    • The program skips the remainder of the code in the try block

    • The program executes the handler code inside the catch clause

    • If none of the catch clause matches the thrown exception, the method exits immediately

If none of the code inside the try block throws an exception, then the program skips the catch clause

    • As a general rule, you should catch those exceptions that you know how to handle

    • Propagate those you do not know how to handle

try

{

String line - reader.readLine();

}

catch (MalformedURLException e1)

{

e1.printStackTrace();

}

catch (IOException e2)

{

e2.printStackTrace();

}

e.printStackTrace()

e.getMessage()

e.getClass().getName()

Rethrowing Exceptions

    • You may need to catch exception without addressing the root cause of it

    • Typical you do local cleanup but it can't fully resolve the problem so rethrow the exception

try

{

...

}

catch (MalformedURLException e)

{

localCleanup();

throw e;

}

The finally Clause

    • This is typically used to cleanup local resources both in normal flow and exception flow

    • Executed if the code throws no exception and code in finally clause

    • Executed if code throws exception, executes code in matching catch clause and code in finally clause

    • Executed if code throws exception, no matching catch clause, code in finally clause and then exception is thrown back to caller

    • You can use the finally clause without a catch clause

try

{

...

}

catch (IOException e)

{

...

}

finally

{

localCleanup();

}

Some Tips on Using Exceptions

    • Exception handling is not supposed to replace a simple test e.g. empty stack pop. Use for exceptional circumstances only

    • Do not micromanage exceptions around every statement, have bigger try block instead

    • Do not squelch exceptions. Handle exception and add trace logging

    • Propagating exceptions is not a sign of shame