Java 212: Exceptions Handling

Post on 11-Feb-2016

41 views 2 download

description

Java 212: Exceptions Handling. Chapter Objectives. Learn what an exception is See how a try / catch block is used to handle exceptions Become aware of the hierarchy of exception classes Learn about checked and unchecked exceptions. Chapter Objectives (continued). - PowerPoint PPT Presentation

Transcript of Java 212: Exceptions Handling

Java 212:Exceptions Handling

Chapter Objectives

• Learn what an exception is• See how a try/catch block is used to

handle exceptions• Become aware of the hierarchy of exception

classes• Learn about checked and unchecked

exceptions

Chapter Objectives (continued)

• Learn how to handle exceptions within a program

• Discover how to throw and rethrow an exception

• Learn how to handle events in a program• A good reference: Sun’s Java Tutorial,

Exceptions Chapter

IntroA major factor in good programming is having your code elegantly handle errors as they arise. Until this point, whenever errors have been generated, we have “handled” the error by simply allowing our programs to crash. Obviously this will not do in the real world.

Though you won’t always be able to anticipate exact errors, you will frequently be able to anticipate certain categories of errors. For example, if you ask a user for some input, you might anticipate getting back a data type different from the type you require. Eg: You ask the user for their age and they enter a data-type other than int (e.g. “fifteen”)

In this lecture we will talk about anticipating different types of errors (aka exceptions) and the appropriate ways of handling those exceptions.

Intro contdBeing an object-oriented language, Java handles errors by generating special exception objects which are automatically instantiated for us behind the scenes when an error occurs.

Java has a special construct called a ‘try’ block that we will now use whenever we workwith code that has the potential of generating particular types of errors (exceptions).

Within a try/catch block, you have the option of “handling” the exception – but you are not required to. You can simply ignore the exception object and allow some other part of the program to “catch” it.

Typically, this “other part of the program” refers to whichever statement invoked the method in which the error was generated.

If no statement in the entire program catches the exception, the program ends abruptly and displays an exception message to the console.

* “Handling” an Exception - OverviewKEY POINT: When an exception is generated, some code, somewhere must “handle” it. If the exception is never handled, the program will crash.

Ideally, all of our code will be ready to handle all possible exceptions.

If we wish to handle an exception, the error (exception) generating code is enclosed in something called a try block. We can handle the exception by following the try block with one or more catch blocks.

If the code that generates the exception is not equipped to handle it (e.g. the code is not enclosed inside a ‘try/catch’ block), the “outer” level (i.e. whichever method called the method with the offending statement) is given the opportunity to handle the exception. If that outer method doesn’t handle it, then the next outer method will be given the opportunity. If Java makes it all the way back to main() and still never handles the exception, the program aborts.

Sometimes we want to delegate the handling of an exception to an outer-level. In that case, we can include a ‘throws’ statement. More on this a little later.

Overview contd• Exceptions tend to be about problems that come up at run-time as

opposed to compile-time.• The compiler will require that you deal with (“handle”) the exception.

– Note that the compiler doesn’t care how you take care of (handle) the exception, it only cares that you are aware of the possibility that an exception can occur and intend todeal with it appropriately.

• You’ll spend much more time handling exceptions than you will creating them.– Most types of exceptions have already been thought of by the people who

created Java. These pre-existing exception classes are automagically instantiated when that type of exception occurs.

– When you invoke a method that can generate an exception (e.g. a method to open a file), it is up to you to have code that can handle the FileNotFound exception that might occur.

– An exception is always thrown back to the caller (the method that invoked whichever method generated the exception).

Example: Handling an Exceptiontry { FileWriter fout = new FileWriter("testFile.txt"); fout.write("test file output"); fout.close();}catch (IOException e) { System.out.println("Error opening file"); //may have other code here...}

If you look at the API for the FileWriter class, you will see that the constructor method that we invoke above has the potential to generate an IOException. Because this exception can be generated, the compiler requires us to place the method call (i.e. the constructor) inside a try block.

Another example

try { FileReader fin = new FileReader("inputFIle.txt"); //code that reads in and works with input}catch (FileNotFoundException e) { System.out.println(“Problem opening the requested file"); //might have code here to try and fix the problem...}

API for the FileReader constructor

This tells us that we must write code that can catch this exception. So…

The Point of all this: “Robust” Programming

One of the most important objectives in programming is to write “fault-tolerant” or “robust” code. That is, we want to write programs in which problems may arise, but the program continues to run.

Good exception handling is one of the more effective methods of making your code “fault-tolerant”, or, “robust”.

Separate Error Handling Logic from Program Logic

Assuming that potential errors will not happen all that frequently, you don’t want your code to spend inordinate amounts of time doing error-checking operations. For example, it is bad form to spend time and space encasing code inside while-loops that look for bad input.

Instead, it is better to allow your program’s logic (main purpose) to function as it should, but to enclose the code in a block that is ready to spring into action if and when problems do occur.

In addition to improving performance, it also improves the clarity of your code.

Check out this example from Sun’s Java Tutorial

Exception• Definition: an occurrence of an undesirable

situation that can be detected during program execution (e.g. as opposed to at compile-time)

• Examples– Division by zero– Trying to open an input file that does not exist– An array index that goes out of bounds

Java’s Mechanism of Exception Handling

• When an exception occurs, an object is instantiated automatically by Java

• The datatype of exception that is generated depends, not surprisingly, on the reason for the exception

• Java provides numerous exception classes to effectively handle certain common exceptions such as division by zero, invalid input, and file not found

• Example: Division by zero is an arithmetic error and is handled by the class ArithmeticException– So, if a division by zero occurs, Java will automatically generate

an object of type ArithmeticException.

Java’s Mechanism of Exception Handling (continued)

• Another example: When a Scanner object is used to input data into a program, any invalid input errors (e.g. a String is entered as input to the method nextInt() ) an exception of type class InputMismatchException is generated

• Note that we have NOT been required to place the nextInt() method call inside a try block. Why not??? – The reason is that some types of exceptions MUST be placed

inside a try block, while others are optional. More on this shortly.– The InputMismatchException that could be generated by the

nextInt() method is one of those ‘optional’ exceptions. Following is an example of placing the code inside a try block:

Scanner console = new Scanner(System.in); int age;

try {System.out.print("How old are you? ");age = console.nextInt();}catch (InputMismatchException e){System.out.println("Error reading in input.");System.out.println("Setting age to -1");age = -1;}

System.out.println("You are " + age + " years old.");

This way of doing things is much preferable to simply having the program crash on you. Later we will show examples of how you might loop until a valid integer is entered.

Don’t forget scope!

• Any variables/objects, etc declared inside the try block is local to that block. When outside of the try block, that is, when it is done or if inside a catch block, those items will no longer be in scope.

• So, you will often need to declare things before entering your try block.

• See the previous example where console and age were declared before the try block.

See: ExceptionExample1.java

• If an exception occurs, the program catches and then handles it.

• You can have several different catch blocks. Which block gets executed will depend on which type of exception occurred.

• Remember that when an exception is generated, Java automatically instantiates an object of that Exception type. You can invoke various methods on that object in order to find out more about it.

• For example, all exception objects have a toString method that you can invoke to find out a little bit about that exception object.

try/catch/finally Block• Statements that might generate an exception are placed in

a try block• The try block might also contain statements that should

not be executed if an exception occurs• The try block is followed by zero or more catch blocks

– A catch block is where the “handling” takes place, and for this reason, is also known as an exception handler

• A catch block specifies the type of exception it can catch and contains an exception handler – Every catch block must specify one (and only one) exception

parameter– e.g. catch (NumberFormatException e)

try/catch/finally Block (contd)

• The last catch block may or may not be followed by a finally block – Another way of stating: Every try block must be followed

by at least one catch block and/or a finally block

• Any code contained in a finally block always executes, regardless of whether an exception actually occurs! – One exception to this rule: When the program exits early from a try

block by calling the method System.exit();

• If a try block has no catch block, then it must have the finally block

try/catch/finally Block (continued)

Optional.

You can include a catch block for every possible exception that might have been generated inside the try block.

try/catch/finally Block (contd)

•If no exception is thrown in a try block, all catch blocks associated with the try block are ignored and program execution resumes after the last catch block•If an exception is thrown in a try block, the remaining statements in the try block are ignored

- The program searches the catch blocks in the order in which they appear after the try block, and looks for an appropriate exception handler by examining the parameter for each catch block in turn

try/catch/finally Block (contd)• If the type of exception matches the parameter type

in one of the catch blocks, the code of that catch block executes and the remaining catch blocks after this catch block are ignored

• If there is a finally block after the last catch block, the finally block always executes (i.e. regardless of whether an exception occured)

* finally Block *• The most common use for a finally block is to close

resources that were created inside the try block. • Recall that resources take up memory!

• For example, when you open various streams (FileReader, BufferedReader, FileWriter, etc) all of them are taking up resources.

• The ideal place to close those streams is NOT at the end of your try block, since if an exception is generated, control will never get as far as that point.

• Instead, close the resources in the finally block. • See FileIOExceptions.java

Order of catch Blocks• The heading of a catch block specifies the type of exception

it handles• A catch block can catch either exceptions of a specific type

– e.g. catch (ArithmeticException e)• or all types of exceptions

– e.g. catch (Exception e)• However, the order can matter! Can you see why?

– If you catch the Exception class first (as opposed to one of its subclasses), that block will always get executed.

– See next slide

Order of catch Blocks (continued)A reference variable of a superclass type can point to an object of its

subclass:• If in the heading of a catch block you declare an exception

using the class Exception, then that catch block will catch all types of exceptions because the class Exception is the superclass of all exception classes

• In a sequence of catch blocks, exceptions of a subclass type should be placed before exceptions of a superclass type– In other words, if you declare the superclass type first, the catch block

containing the subclass type will never be executed

Parent Exception Class• All exception classes are inherited from class Exception which in turn, inherits from class Throwable

• Most of the methods we invoke using our exception objects come from the class Throwable.

Java Exception Hierarchy

It is not difficult to create your own exception classes by extending the class Exception. In the real world, most programmers rarely need to do so.

Java Exception Hierarchy (continued)

Java’s Exception Class• class Exception

– Subclass of class Throwable – Superclass of classes designed to handle exceptions

• There are many different types of exceptions:– I/O exceptions (e.g. for opening / closing files)– Number format exceptions– File not found exceptions– Array index out of bounds exceptions

• Exceptions categorized into separate classes and contained in various packages

Java Exception Hierarchy (continued)

Java Exception Hierarchy (continued)

Java Exception Hierarchy (continued)

Some Java Exception Classes

Some Java Exception Classes (contd)

Some exceptions from the Scanner class

API for nextInt() method

Java Exception Classes (continued)

Java Exception Classes (continued)

Java Exception Classes (continued)

* Checked vs Unchecked ExceptionsExceptions are classified into two types: Checked and Unchecked. If an exception is UN-checked, you are NOT required to place it inside a try/catch block and handle it. (Though you may choose to do so).

An unchecked exception is one that you are not required to provide for. For example, the nextInt() method of the Scanner class throws un-checked exceptions which is why we haven’t had to write code to hande them.

A checked exception is one that the compiler requires you to provide for; that is, you must notify Java that you are aware that this exception might occur and that somewhere in your code, you are going to handle it. Your compiler will refuse to compile if you don’t. For example, a FileNotFoundException is a checked exception, and is generated when you write code that is supposed to open a file for reading or writing.

•The FileNotFound exception can be generated in many places, such as when you attempt to open a File for reading input. This is why you had to enclose that code inside a try block.

Checked Exception: “Catch or Declare”As was just mentioned, the compiler requires you to anticipate checked exceptions. It does so by enforcing a “catch or declare requirement” for checked exceptions.

Option 1: Catch the exception:So far, we have handled checked exceptions by enclosing the code inside a try block and handling the code via a catch and/or finally block(s).

Option 2: Declare via a ‘throws’ clause.The throws clause is part of your method signature. This clause indicates that the code inside your method may generate an exception, but that your method does not handle that exception (or handles it incompletely). We will discuss the throws clause shortly.

class RuntimeException • Exceptions that inherit from this class are the only kinds of

exceptions that do NOT have be enclosed in a try block.– In other words, these are unchecked exceptions– e.g. ArrayIndexOutOfBounds

• Therefore, all other types of exceptions (that are not subclasses of RuntimeException) do need to be enclosed in try blocks.– These are called checked exceptions.– Any code that you write that invokes a method that can generate an

exception must be caught. If you neglect to do this, your program won’t compile.

Summary: Checked vs Unchecked

• All exceptions that are not subclasses of RuntimeException must be checked (placed inside a try block) or thrown.– Class that are NOT of type RuntimeException are “checked”

exceptions • Must be placed inside a try block

– Subclasses of RuntimeException are unchecked exceptions.• Do not require a try block

Mnemonic:

rUNtime = UNchecked!

Review: Checked Exceptions• Definition: any exception that can be recognized by the compiler (i.e. that

the compiler requires you to anticipate). • All subclasses of Exception except for subclasses of RuntimeException

are Checked exceptions.• Examples

– IOException– FileNotFoundException

• For example, see the API for the constructor of the FileReader or PrintWriter classes)

• So, if you are writing a method that has code that can generate a checked exception, you must either:

1) Place the code inside a try block OR2) Throw the exception

Unchecked Exceptions• Exceptions that can only be recognized at “run-time” (when the

program is being executed). For example, code that requires user input.– These must be checked for by programmer

• All subclasses of RuntimeException are unchecked exceptions

• Examples– Division by zero– Array index out of bounds

• Hopefully this makes sense. When the program is being compiled, it may not be possible for the compiler to know if a division by zero will occur. Therefore, the compiler does not check for this exception at compile-time.

– Example: See the parseInt() method of the Integer class from the API

* The class Exception and the Operator instanceof

• Recall that a reference of a superclass type can point to objects of its subclass

• You can determine if a reference variable points to an object using the operator instanceof

• You can combine catch blocks using this facility

try {

System.out.print("Enter the " + "dividend: "); dividend = console.nextInt(); System.out.println(); System.out.print("Enter the " + "divisor: "); divisor = console.nextInt(); System.out.println(); quotient = dividend / divisor; System.out.println("Quotient = " + quotient); }

catch (Exception eRef){

if (eRef instanceof ArithmeticException) System.out.println("Exception “

+ eRef.toString()); else if (eRef instanceof InputMismatchException) System.out.println("Exception "

+ eRef.toString()); }

The class Exception and the Operator instanceof

* Throwing an Exception

• Recall that one option for dealing with checked exceptions is to ‘declare’ the exception. This is done via the throws caluse.

• This clause indicates that your method does not handle (or incompletely handles) the exception.

• So where does the handling occur? One way is to handle the exception inside the method invoked the current (exception-generating) method. – However, this outer method can ‘rethrow’ the exception to its calling

method.– See DivisionExceptionExampleWithThrows.java

Rethrowing an Exception

• As you know, when an exception occurs in a try block, control immediately passes to one of the catch blocks.

• Typically, a catch block does one of the following:– Completely handles the exception (the examples we’ve been

examining up to this point)– Throws the same exception for the calling (outer) environment

to handle the exception• This can be useful if you have a lot of error code grouped in one place. You

can throw the exception to the outer method where this error code was placed.

– Partially processes the exception; in this case, the catch block either re-throws the same exception or throws another exception for the calling environment to handle

Throwing = “Ducking”

• For now, you can think of throwing an exception as “ducking” it. That is, you are saying that the current method “ducks” and is going to let the exception fly on by.

• So who will catch the exception? Answer: Whichever method invoked the method that generated the exception.

• Ultimately, however, the exception must be caught. If not, the program aborts.

“Throwing” an Exception

• Useful when: – catch block catches exception but is unable to handle

it– catch block decides exception should be handled by

calling environment• Allows programmer to provide exception

handling code in one place• Syntax:

throw exceptionReference; //ORthrow new Exception();

import java.util.*;public class RethrowExceptionExmp1{ static Scanner console = new Scanner(System.in); public static void main(String[] args) { int number; try { number = getNumber(); System.out.println("Line 5: number = " + number); } catch (InputMismatchException imeRef) { System.out.println("Line 7: Exception " + imeRef.toString()); } }}

Throwing an Exception (continued)

Code is continued on next slide…

public static int getNumber() throws InputMismatchException { int num; try { System.out.print("Line 11: Enter an “ + "integer: "); num = console.nextInt(); System.out.println(); return num; } catch (InputMismatchException imeRef) { throw imeRef;

// Rather than handle the exception, the // method RETHROWS the exception

} }}

Rethrowing and Throwing an Exception (continued)

The exception is rethrown to whichever line of code invoked the getNumber() method. The other important requirment is that the outer environment (i.e. the main() method in this example), is ready to handle an exception of type InputMismatchException

A method declaration must specify checked exceptionsWhen we write a method containing code that has the potential to throw a checked exception, we must include a ‘throws’ clause in the header. Why did the designers of Java require this clause to be included?

Answer: We are familiar with the idea that a method should be a “black box”, that is, all we should need to know about the method is its header, and what the method does. However, because the inner workings of the method are not known to the user, the programmer must also warn the user of his/her method that there is the possibility for certain exceptions to be generated. This way, when a user invokes the method, they have the option to write code to catch and handle the exception should that exception be generated.

According to Sun’s Java tutorial: “These exceptions are as much a part of that method's programming interface as its parameters and return value. ”

Exceptions Example Codepublic static void doStuff() throws InputMismatchException, FileNotFoundException{ //code that might generate //checked exceptions

}

• Because this method can generate checked exception(s) but does not have code to handle it, we must include the throws clause.

• If the method DID handle both of these exceptions, we could have left out the throws clause.

Example

RethrowExceptionExmp2.java

Notice that the output generated by the toString() methods of the two exceptions are different even though the exception types are idnetical. This is because they are, in fact, two entirely different exception objects.

* The Method printStackTrace

• Used to determine the order in which the methods were called and where the exception was handled

• Java keeps track of the sequence of method calls in a program. When an exception occurs in a method, you can invoke the method printStackTrace() (which comes courtesy of the Throwable class) to determine the order in which the methods were called and where the exception was handled.

• See: PrintStackTraceExample1.java• See: PrintStackTraceExample2.java

import java.io.*;public class PrintStackTraceExample1{ public static void main(String[] args) { try { methodA(); } catch (Exception e) { System.out.println(e.toString() + " caught in main"); e.printStackTrace(); } }

The Method printStackTrace (continued)

public static void methodA() throws Exception { methodB(); } public static void methodB() throws Exception { methodC(); } public static void methodC() throws Exception { throw new Exception("Exception generated " + "in method C"); }}

The Method printStackTrace (continued)

• Sample Run

java.lang.Exception: Exception generated in method C caught in mainjava.lang.Exception: Exception generated in method C at PrintStackTraceExample1.methodC (PrintStackTraceExample1.java:30) at PrintStackTraceExample1.methodB (PrintStackTraceExample1.java:25) at PrintStackTraceExample1.methodA (PrintStackTraceExample1.java:20) at PrintStackTraceExample1.main (PrintStackTraceExample1.java:9)

The Method printStackTrace

Note: Because the methods A and B do not handle the exception thrown by C, they (A and B) must include the ‘throws’ clause in their heading. Note how in PrintStackTraceExample2, methodA() does not include a Throws clause.

* Exception-Handling TechniquesThe programmer typically has three options:• Terminate program

– Output appropriate error message upon termination• Fix error and continue

– E.g. Repeatedly get user input on an InputMismatchException– Output appropriate error message until valid value is entered– Definitely review: ExceptionExampleWithLoop.java – Note the elegant

use of the boolean in this program – you definitely should learn to use this technique.• Log error and continue

– Write error messages to file and continue with program execution– e.g. Your program is running a nuclear reactor or driving the space shuttle– However, logging the errors is obviously (I hope) vital!

Unrelated but important note: Note the use of the additional str = console.nextLine() in the catch block. This is because when an exception is thrown by any nextZZZ() method, the entry (“token”) is still in the input stream. So we need to read it in to ‘str’ as a way of removing it out of the input stream.

Optional if Time: Creating Your Own Exception Classes

• While Java has many built-in exception classes, it is impossible to anticipate the infinite number of exceptions that can be generated for a specific program. – Eg: A program to drive the space shuttle would have many particular exceptions to anticipate

• That being said, most Java programmers rarely have to write exception classes in the real world.

• Every exception class you define extends class Exception or one of its subclasses• Typically, your derived Exception class should only include constructor methods• Syntax to throw your own exception object: throw new ExceptionClassName(messageString);

*Don’t forget that because you inherit from Exception, your excaption class can also invoke the methods from the Throwable class such as getMessage() and toString() .

Creating Your Own Exception Classes contd

public class MyDivisionByZeroException extends Exception{ public MyDivisionByZeroException() { super("Cannot divide by zero"); }

public MyDivisionByZeroException(String strMessage) { super(strMessage); }}

Exceptions are for unavoidable situations• Exceptions are for handling situations that arise that you (the

programmer) can not control for. Exceptions are NOT for handling flaws in your code.

• In other words, don’t use exceptions to deal with array boundaries – those are things the programmer should avoid with proper testing.

• Do use exceptions to deal with situations that can cause your program to malfunction, but for which you can not control. – Bad user input– File not present / can’t be opened

< / Exceptions >

Event Handling – Rev and contd…

• Action events – Handled by implementing interface ActionListener

• Window events – Handled by implementing interface WindowListener

• Mouse events – Handled by implementing interface MouseListener

• Key events – Handled by implementing interface KeyListener

WindowListener Interfacepublic interface Windowlistener {

public void windowClosed(WindowEvent e); public void windowOpened(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDeactivated(WindowEvent e); public void windowClosing(WindowEvent e);

}

Recall that your class would have to write bodies for all of these methods. Most of the time, however, you only are interested in writing a useful body for one or two of them.

Event Handling – Adapter Classes

• Adapter classes are simply conveniences. They are classes that implement interfaces, but provide empty methods for all the abstract methods of the interface.

• You can now extend the adapter class and then simply override whichever methods you want to use.

• class WindowAdapter – Implements interface WindowListener with empty bodies to all methods

• class MouseAdapter – Implements interface MouseListener with empty bodies to all methods

WindowListener and its Adapterpublic interface Windowlistener {

public void windowClosed(WindowEvent e); public void windowOpened(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDeactivated(WindowEvent e); public void windowClosing(WindowEvent e);

}

public class WindowAdapter implements WindowListner{

public void windowClosed(WindowEvent e){} public void windowOpened(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} public void windowClosing(WindowEvent e){}

}

Your class:

public class MyWindowHandler extends Window Adapter{

public void windowClosed(WindowEvent e) { //code to respond to window closed event…

}}

public class WindowAdapter implements WindowListner{

public void windowClosed(WindowEvent e){} public void windowOpened(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} public void windowClosing(WindowEvent e){}

}

Registering Listeners• Recall that to add an action listener to a component, we used the

command:– submitB.addActionListener(…)

• There are corresponding add???Listener methods for the various types of events.

• Registering window listener object to GUI component– Use method addWindowListener– Window listener object being registered is passed as parameter to method addWindowListener

• Registering mouse listener object to GUI component– Use method addMouseListener– Mouse listener object being registered is passed as parameter to method addMouseListener

Using an Anonymous Class with an Adapter

(Discussed on page 815 of Malik 4th ed – will not be tested)

calculateButton.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } //end method windowClosing } //end WindowAdapter class !!); //close the parameter list

Event Handling (continued)

Event Handling (continued)

Event Handling (continued)

Chapter Summary• Exception

– Definition• Handling exceptions within a program

– try/catch/finally block– Order of catch blocks– Using try/catch blocks in a program– The class Exception and the Operator instanceof– Rethrowing and throwing an exception

• Exception– Hierarchy – Classes

Chapter Summary (continued)

• Checked and Unchecked Exceptions• The method printStackTrace• Exception handling techniques

– Terminate program– Fix error and continue– Log error and continue

• Creating your own exception classes• Event Handling