Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Java Exception Handling
●
Exception = an event that occurs during the
execution of a program that disrupts the normal
flow of instructions:
–
●
●
Examples: Hard disk crash; Out of bounds array
access; Divide by zero, etc
When an exception occurs, the executing method
creates an Exception object and hands it to
the runtime system--``throwing an exception''
The runtime system searches the runtime call
stack for a method with an appropriate handler,
which ``catches the exception''
Java's Exception Handling Policy
●
●
Java is fussy about (some) exceptions, requiring
that the programmer either:
–
deal with the exceptions when they occur, using try
and catch, or
–
explicitly hand off the exception to the method that
calls the method in which the exception occurs,
effectively ``passing the buck'' to the calling method.
The exceptions Java is fussy about are called
``checked'' exceptions, because the compiler will
check that one of the above options is satisfied
Advantages of Java Exception
Handling
1. Separating Error Handling Code from ``Regular''
Code
2. Propagating Errors Up the Call Stack
3. Grouping Error Types and Error Differentiation
Advantage 1:
Separating Error Handling Code from
``Regular'' Code
Example: Here is pseudocode for reading a file into
memory:
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
Problems with readFile
●
●
●
What happens if the file can't be opened?
What happens if the length of the file can't be
determined?
What happens if enough memory can't be
allocated?
●
What happens if the read fails?
●
What happens if the file can't be closed?
Error Handling With Traditional
Programming
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
Error Handling With Java
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
Note that the error handling code and ``regular'' code are
separate
Advantage 2:
Propagating Errors Up the Call Stack
method1 {
call method2;
}
method2 {
call method3;
}
method3 {
call readFile;
}
readFile
call
call
call
method3
method2
method1
Call Stack
Suppose also that method1 is the only method
interested in the errors that occur within readFile.
How does the error code get propogated up the stack?
Propagating Errors Using Traditional
Programming
method1 {
errorCodeType error;
error = call method2;
if (error)
doErrorProcessing;
else
proceed;
}
errorCodeType method2 {
errorCodeType error;
error = call method3;
if (error)
return error;
else
proceed;
}
errorCodeType method3 {
errorCodeType error;
error = call readFile;
if (error)
return error;
else
proceed;
}
readFile
call
call
call
method3
return
return
method2
method1
Call Stack
return
Propagating Errors Using Java
method1 {
try {
call method2;
} catch (exception) {
doErrorProcessing;
}
}
method2 throws exception {
call method3;
}
method3 throws exception {
call readFile;
}
readFile
call
call
call
method3
method2
method1
Call Stack
throw
Advantage 3:
Grouping Error Types and Error
Differentiation
Java exceptions are first class Java objects, and so they
are grouped into a class hierarchy. For example:
Exception
RunTimeException
NullPointerException
ArithmeticException
IOException
FileNotFoundException
MalformedURLException
Example
Suppose (remember, this is pseudocode):
method1 {
try {
call method2;
}
catch(Exception) {
doErrorProcessing;
}
}
method2 throws ArithmeticException {
... call method3; ...
}
method3 throws FileNotFoundException {
... call method4; ...
}
method4 throws NullPointerException {
...
}
Throwing Structure
call
call
call
method4
method3
method2
throw
method1
Call Stack
In this case, the exception handler in method1 must
handle all exception types
Modified Example
method1 {
try {
call method2;
}
catch(RunTimeException) {
doErrorProcessing;
}
}
method2 throws ArithmeticException {
... call method3; ...
}
method3 throws FileNotFoundException {
... call method4; ...
}
method4 throws NullPointerException {
...
}
New Throwing Structure
call
call
call
method4
method3
throw
method2
method1
Call Stack
In this case, method1 will handle only runtime
exceptions.
Any FileNotFoundException thrown by
method3 will have to be handled further down the stack.
Another Modified Example
method1 {
try {
call method2;
}
catch(RunTimeException) {
doErrorProcessing;
}
}
method2 throws ArithmeticException {
try {
... call method3; ...
}
catch(IOException) {
doMoreErrorProcessing;
}
}
method3 throws FileNotFoundException {
... call method4; ...
}
method4 throws NullPointerException {
...
}
New Throwing Structure
call
call
call
method4
method3
method2
method1
Call Stack
throw
FileCopy Example Revisited
import java.io.*;
public class FileCopy {
public static void main(String[] args) throws IOException {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
FileReader r;
FileWriter w;
System.out.print("Source file name: ");
String inFileName = br.readLine();
r = new FileReader(inFileName);
System.out.print("Destination file name: ");
String outFileName = br.readLine();
w = new FileWriter(outFileName);
int c;
while ((c = r.read()) != -1)
w.write(c);
w.flush();
}
If The Input File Does Not Exist
In the example, the main method chooses to ``pass
the buck,'' but there is nowhere to pass it to.
Thus, the program will crash:
4% java FileCopy
Source file name: foo
Exception in thread "main" java.io.FileNotFoundException: foo
(No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at java.io.FileReader.<init>(FileReader.java:39)
at FileCopy.main(FileCopy.java:12)
5%
Catching the Exception
public class FileCopy {
public static void main(String[] args) throws IOException {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
FileReader r;
FileWriter w;
System.out.print("Source file name: ");
String inFileName = br.readLine();
try {
r = new FileReader(inFileName);
}
catch(FileNotFoundException ex) {
System.out.println(ex.getMessage());
System.out.print("Source file name: ");
inFileName = br.readLine();
r = new FileReader(inFileName);
}
...
}
}
Catching the Exception (cont'd)
This approach will catch the first instance of a
FileNotFoundException, but only that instance:
5% java FileCopy
Source file name: foo
foo (No such file or directory)
Source file name: bar
Exception in thread "main" java.io.FileNotFoundException: bar
(No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at java.io.FileReader.<init>(FileReader.java:39)
at FileCopy.main(FileCopy.java:19)
6%
Note that you can use the getMessage() method
(inherited by the Exception class) in your handler.
Generating True Looping Behavior
public class FileCopy {
public static void main(String[] args) throws IOException {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
FileReader r = null;
FileWriter w = null;
boolean fileFound;
do {
fileFound = true;
System.out.print("Source file name: ");
String inFileName = br.readLine();
try {
r = new FileReader(inFileName);
}
catch(FileNotFoundException ex) {
fileFound = false;
System.out.println(ex.getMessage());
}
} while ( !fileFound );
...
}
}
New Output
226% java FileCopy
Source file name: foo
foo (No such file or directory)
Source file name: bar
bar (No such file or directory)
Source file name: foo
foo (No such file or directory)
Source file name: bar
bar (No such file or directory)
Source file name: X.java
Destination file name: Y.java
227%
Another Way
public static void main(String[] args) throws IOException {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
FileReader r = getFileReader(br);
FileWriter w = getFileWriter(br);
int c;
while ((c = r.read()) != -1)
w.write(c);
w.flush();
}
Generating Looping Behavior
Through Recursion
private static FileReader getFileReader(BufferedReader br) {
System.out.print("Source file name: ");
try {
String inFileName = br.readLine();
return new FileReader(inFileName);
}
catch(IOException ex) {
System.out.println(ex.getMessage());
return getFileReader(br);
}
}
Note: No looping code needed.
Since the exception is caught, no throws clause
is necessary.
Generating Looping Behavior
Through Recursion (cont'd)
private static FileWriter getFileWriter(BufferedReader br) {
System.out.print("Destination file name: ");
try {
String outFileName = br.readLine();
return new FileWriter(outFileName);
}
catch(IOException ex) {
System.out.println(ex.getMessage());
return getFileWriter(br);
}
}
Now the only calls in main that can throw an exception
are read, write, and flush
A Version of main that Does Not
throw
public static void main(String[] args) {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
FileReader r = getFileReader(br);
FileWriter w = getFileWriter(br);
int c;
try {
while ((c = r.read()) != -1)
w.write(c);
w.flush();
}
catch(IOException ex) {
System.out.println(ex.getMessage());
}
}
Now the program will not crash if/when an I/O error
occurs.
Checked vs. Unchecked Exceptions
●
●
A program that catches all I/O exceptions may
still experience a different type of exception (say,
a runtime exception)
I/O exceptions are ``checked'' by the compiler
–
●
That is, you are required to either catch them or
mention them in a throws clause
Unlike I/O exceptions, runtime exceptions are
``unchecked''
–
That is, you can choose to ignore them at your peril
Some Checked Exceptions
●
●
●
IOException and any of its subclasses
InterruptedException (thrown when a
thread is interrupted)
Any exception you invent by subclassing
Exception
Some Unchecked Exceptions
●
Subclasses of RuntimeException:
–
–
–
–
ArithmeticException
IllegalArgumentException
NumberFormatException
IndexOutOfBoundsException
●
●
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
–
NullPointerException
–
Those that you invent by subclassing
RuntimeException
Exceptions vs. Errors
●
●
Exceptions are processing conditions that a
program ought to be able to recover from if it is
robust enough
Errors are conditions that are ordinarily not
recoverable:
–
Death of a thread
–
Linking error
–
Virtual machine error
The Throwable Class
●
Exceptions and Errors are both subclasses
of the Throwable class:
Object
Throwable
Exception
LinkageError
Error
ThreadDeath
VirtualMachineError