| CS 535: Object-Oriented Programming & Design |
|
---|
Fall Semester, 1997
Doc 16, Exceptions
To Lecture Notes Index
San Diego State University -- This page last updated 09-Oct-97
Contents of Doc 16, Exceptions
- References
- Exceptions
- Issues
- How is the exception raised?
- Where can the Handler be placed?
- How is the handler for the exception found?
- Finding the handler for Unchecked exception
- Finding the handler for Checked exceptions
- Multiple Exceptions
- What is executed after the handler has finished?
- Final Block - For Clean Up
- What information is passed to the handler?
- User Defined Exceptions
- Tips on Using Exceptions
- List of All Java 1.0 Built-in Exceptions
The Java Programming Language, Arnold and Gosling, Chapter 7
Out-of Bounds
Java checks the bounds of arrays
class ArrayOutOfBounds
{
public static void main( String args[] )
{
int students[] = new int[5];
students[ 10 ] = 1;
System.out.println( " The End" );
}
}
Output
java.lang.ArrayIndexOutOfBoundsException: 10
at ArrayOutofBounds.main(All.java:8)
Exception Handling
In a program there are events which may be considered exceptional or unusual
- Error conditions
- On zero divide have the program do some recovery process or give some
debugging information
-
- Special conditions
-
- If a plane is about to collide midair the navigation program should perform
some special operation
Exceptional cases can be handled by explicit tests
Boolean computeFoobar( ) {
Boolean zeroDivideFlag = false;
if ( A * A - 2 * B = 0 )
zeroDivideFlag = true;
else
result = sqrt( C )/ ( A * A - 2 * B )
return zeroDivideFlag
}
// in main
flag = computeFoobar( )
if ( flag == true )
// now what?
Definitions
Exception
-
- A condition that is detected by an operation, that cannot be resolved
within the local context of the operation, and must be brought to the attention
of the operation's invoker
-
Exception handler or handler
- The procedure or code that deals with the exception
-
Raising the exception
- The process of noticing the exception, interrupting the program and calling
the exception handler
-
Propagating the exception
- Reporting the problem to a higher authority (the calling program)
-
Handling the exception
- Taking appropriate corrective actions
-
Languages with Exception Handling
PL1, Clu, ADA, Mesa, C++, Smalltalk, Java
How is the exception raised?
Where can the Handler be placed - Scope of handler
How is the handler for the exception found?
- All languages find the handler dynamically
What is executed after the handler has finished?
What information is passed to the handler?
Implicitly by some error condition
class ImplicitlyRaisedException
{
public static void main( String[] arguments )
{
int students[] = new int[5];
students[ 10 ] = 1; // Exception occurs here
}
}
Explicitly by the Programmer
class ExplicitlyRaisedException
{
public static void main( String[] arguments )
{
throw new ArrayIndexOutOfBoundsException()
}
}
Out-of Bounds - With try
class ArrayOutOfBounds
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After assignment statement" );
}
// catch is the handler
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
};
System.out.println( " After try " );
}
}
Output
Start Try
OutOfBounds: 10
After try
try and catch must be together
try
and catch are not separate blocks
try and catch are one construct
class NeedCatchWithTryBlock
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After assignment statement" );
}
System.out.println( " After try " ); // Compile error
}
}
Compile Error
All.java:15: 'try' without 'catch' or 'finally'.
System.out.println( " After try " );
try and catch must be together
try
and catch are not separate blocks
try and catch are one construct
class NeedTryWithCatch
{
public static void main( String args[] )
{
int students[] = new int[5];
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After assignment statement" );
// catch is the handler
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
};
System.out.println( " After try " );
}
}
Compile Error
'catch' without 'try'.
catch (ArrayIndexOutOfBoundsException e)
try and catch must be together
try
and catch are not separate blocks
try and catch are one construct
class CanNotHaveCodeBetweenTryAndCatch
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After assignment statement" );
}
int DontHaveCodeHere = 5 / 32; // Error here
// catch is the handler
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
};
System.out.println( " After try " );
}
}
Compile Error
'try' without 'catch' or 'finally'.
int DontHaveCodeHere = 5 / 32;
'catch' without 'try'.
catch (ArrayIndexOutOfBoundsException e)
The rules are slightly different for the two types of exceptions: Checked and
Unchecked
Checked
- Methods are required to state if they throw these exceptions
Unchecked
- Standard runtime exceptions and errors
- Methods are not required to state if they throw these exceptions
-
- Subclasses of RuntimeException and Error are unchecked
AWTError | ArithmeticException |
LinkageError | ArrayStoreException |
ClassCircularityError | ClassCastException |
ClassFormatError | EmptyStackException |
IncompatibleClassChangeError | IllegalArgumentException |
AbstractMethodError | IllegalThreadStateException |
IllegalAccessError | NumberFormatException |
InstantiationError | IllegalMonitorStateException |
NoSuchFieldError | IndexOutOfBoundsException |
NoSuchMethodError | ArrayIndexOutOfBoundsException |
NoClassDefFoundError | StringIndexOutOfBoundsException |
UnsatisfiedLinkError | NegativeArraySizeException |
VerifyError | NoSuchElementException |
ThreadDeath | NullPointerException |
VirtualMachineError | SecurityException |
InternalError | StackOverflowError |
OutOfMemoryError | UnknownError |
Unchecked Exceptions: Search the stack for the first enclosing try block
class FindHandlerSimpleExample
{
public static void change( int[] course )
{
System.out.println( "Start Change" );
course[ 10 ] = 1;
System.out.println( "End Change" );
};
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
change( students );
System.out.println( "After change" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
System.out.println( "After try " );
}
}
Output
Start Try
Start Change
OutOfBounds: 10
After try
Finding handler for Unchecked Exceptions
class FindHandlerDoubleExample {
public static void doubleChange( int[] course ) {
System.out.println( "Start Double Change" );
course[ 10 ] = 1;
System.out.println( "End Double Change" );
};
public static void change( int[] course ) {
System.out.println( "Start Change" );
doubleChange( course );
System.out.println( "End Change" );
};
public static void main( String args[] ) {
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
change( students );
System.out.println( "After change" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
System.out.println( "After try " );
}
}
Output
Start Try
Start Change
Start Double Change
OutOfBounds: 10
After try
Finding handler for Unchecked Exceptions
class FindHandlerTwoTryBlocks {
public static void change( int[] course ) {
try
{
System.out.println( "Start Change" );
course[ 10 ] = 1;
System.out.println( "End Change" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "Change Catch: " + e.getMessage());
}
};
public static void main( String args[] ) {
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
change( students );
System.out.println( "After change" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "Main Catch: " + e.getMessage());
}
System.out.println( "After try " );
}
}
Output
Start Try
Start Change
Change Catch: 10
After change
After try
Finding handler for Unchecked Exceptions
What happens if there is no try block?
class NoHandler
{
public static void change( int[] course )
{
System.out.println( "Start Change" );
course[ 10 ] = 1;
System.out.println( "End Change" );
};
public static void main( String args[] )
{
int students[] = new int[5];
System.out.println( "Start Try" );
change( students );
System.out.println( "After change" );
}
}
Output
Start Try
Start Change
java.lang.ArrayIndexOutOfBoundsException: 10
at test.main(classNotes.java)
Check Exceptions must be either:
- handled in the method they are thrown or
-
- the method in which they are thrown must state they will throw the
exception
import sdsu.io.ASCIIInputStream;
import java.io.*;
class CheckedExceptionDeclaredInMethod {
public static void readSomething() throws IOException
{
System.out.println( "Please type an integer: " );
int youTyped;
ASCIIInputStream input = new ASCIIInputStream(System.in);
youTyped = input.readInt(); // throws IOException
};
public static void main( String args[] ) {
try
{
System.out.println( "Start Try" );
readSomething();
System.out.println( "After readSomething" );
}
catch (IOException e)
{
System.err.println( "IO error: " + e.getMessage());
}
System.out.println( "After try " );
}
}
Finding the handler for Checked exceptions
class CheckedExceptionHandledInMethod
{
public static void readSomething()
{
try
{
System.out.println( "Please type an integer: " );
int youTyped;
ASCIIInputStream input;
input = new ASCIIInputStream(System.in);
youTyped = input.readInt(); // throws IOException
}
catch (IOException e)
{
System.err.println( "IO error: " + e.getMessage());
}
};
public static void main( String args[] )
{
System.out.println( "Start Try" );
readSomething();
System.out.println( "After readSomething" );
}
}
Finding the handler for Checked exceptions
class IfYouDontDeclaredInMethod
{
public static void readSomething()
{
System.out.println( "Please type an integer: " );
int youTyped;
ASCIIInputStream input = new ASCIIInputStream(System.in);
youTyped = input.readInt(); // throws IOException
};
public static void main( String args[] ) {
try
{
System.out.println( "Start Try" );
readSomething();
System.out.println( "After readSomething" );
}
catch (IOException e)
{
System.err.println( "IO error: " + e.getMessage());
}
System.out.println( "After try " );
}
}
Compile Error
Error : Exception java.io.IOException must be caught, or it must be declared in the throws clause of this method.
line 12 youTyped = input.readInt();
Error : Exception java.io.IOException is never thrown in the body of the corresponding try statement.
line 22 catch (IOException e)
Finding the handler for Checked exceptions
class SometimesItMakesSenseToDoBoth
{
public static void readSomething() throws
{
try
{
System.out.println( "Please type an integer: " );
int youTyped;
ASCIIInputStream input;
input = new ASCIIInputStream(System.in);
youTyped = input.readInt(); // throws IOException
}
catch (IOException e)
{
System.err.println( "IO error: " + e.getMessage());
throw e;
}
};
public static void main( String args[] ) {
try
{
readSomething();
}
catch (IOException e)
{
System.err.println( "Error: " + e.getMessage());
}
System.out.println( "After try " );
}
}
class MultipleExceptions
{
public static void main( String args[] )
{
int students[] = new int[5];
int classSize = 0;
try
{
System.out.println( "Start Try" );
int classAverage = 10 / classSize;
System.out.println( "After class average" );
students[ 10 ] = 1;
System.out.println( "After array statement" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
catch ( ArithmeticException e )
{
System.err.println( " Math Error" + e.getMessage() );
}
System.out.println( " After try " );
}
}
Output
Start Try
Math Error/ by zero
After try
One Size Fits All Exception
class MultipleExceptions
{
public static void main( String args[] )
{
int students[] = new int[5];
int classSize = 0;
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After array statement" );
int classAverage = 10 / classSize;
}
catch ( Exception e ) // Not a good idea
{
System.err.println( "Exception:" + e.getMessage());
e.printStackTrace();
}
System.out.println( " After try " );
}
}
Output
Start Try
Exception:10
java.lang.ArrayIndexOutOfBoundsException: 10
at MultipleExceptions.main(All.java:11)
After try
Beware of Order
class MultipleExceptions
{
public static void main( String args[] )
{
int students[] = new int[5];
int classSize = 0;
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After array statement" );
int classAverage = 10 / classSize;
}
catch ( Exception e )
{
System.err.println( "Exception:" + e.getMessage());
e.printStackTrace();
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
System.out.println( " After try " );
}
}
Compile Error
All.java:21: catch not reached.
} catch (ArrayIndexOutOfBoundsException e) {
^
1 error
Select the First Exception That Applies
class MultipleExceptions
{
public static void main( String args[] )
{
int students[] = new int[5];
int classSize = 0;
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After array statement" );
int classAverage = 10 / classSize;
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " +
e.getMessage());
}
catch ( Exception e )
{
System.err.println( "Exception:" + e.getMessage());
e.printStackTrace();
}
System.out.println( " After try " );
}
}
Output
Start Try
OutOfBounds: 10
After try
The line of code after the try block
Finally blocks change this slightly
class ArrayOutOfBounds
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After assignment statement" );
}
// catch is the handler
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
};
System.out.println( " After try " );
}
}
Output
Start Try
OutOfBounds: 10
After try
class FinalBlockWithExceptionCalled
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
System.out.println( "After array statement" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
finally
{
System.out.println( "In Final Block" );
}
System.out.println( " After try " );
}
}
Output
OutOfBounds: 10
In Final Block
After try
Final Block - Always Called
class FinalBlockExceptionNotCalled
{
public static void main( String args[] )
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 2 ] = 1;
System.out.println( "After array statement" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " + e.getMessage());
}
finally
{
System.out.println( "In Final Block" );
}
System.out.println( " After try " );
}
}
Output
Start Try
After array statement
In Final Block
After try
Can't Escape Finally
class ExceptionFunction
{
public static boolean change( int[] course )
{
try
{
System.out.println( "Start change" );
course[ 10 ] = 1;
System.out.println( "End Change" );
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println( "OutOfBounds: " );
return true;
}
finally
{
System.out.println( "In Final Block" );
}
return false;
};
public static void main( String args[] )
{
int students[] = new int[5];
System.out.println( "Main" );
System.out.println( change( students ) );
System.out.println( "After Change" );
}
}
Output
Main In Final Block
Start Change true
OutOfBounds: After Change
Finally is Master
A finally block is entered with a reason, such as end of the method, an
exception was thrown
If the finally block creates it own reason to leave ( throws an exception,
executes a return or break) then the original reason is forgotten
class FinalExample
{
public static void explainThis()
{
int students[] = new int[5];
try
{
System.out.println( "Start Try" );
students[ 10 ] = 1;
}
finally
{
System.out.println( "In Final Block" );
return;
}
}
public static void main( String args[] )
{
try
{
explainThis();
}
catch (ArrayIndexOutOfBoundsException missed)
{
System.out.println( "In ArrayIndexOutOfBoundsException" );
}
System.out.println( "After try in main" );
}
}
Output
Start Try
In Final Block
After try in main
Exceptions inside Exceptions
class ExceptionFunction {
public static boolean change( int[] course ) {
try {
System.out.println( "Start change" );
course[ 10 ] = 1;
}
catch (ArrayIndexOutOfBoundsException e) {
course[ 10 ] = 1;
System.err.println( "OutOfBounds: " );
return true;
}
finally {
System.out.println( "In Final Block" );
}
return false;
};
public static void main( String args[] ) {
try {
int students[] = new int[5];
System.out.println( "Main" );
System.out.println( change( students ) );
System.out.println( "After Change" );
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println( "Over Here" );
}
}
}
Output
Main
Start change
In Final Block
Over Here
Two pieces of information are standard
- Message
-
- Stack Info
When you define your own exceptions you can add more data if needed
class FindHandlerSimpleExample {
public static void change( int[] course ) {
course[ 10 ] = 1;
};
public static void main( String args[] ) {
int students[] = new int[5];
try {
change( students );
}
catch (ArrayIndexOutOfBoundsException e) {
System.err.println( "Message: " + e.getMessage() );
System.err.println( "Stack: " + e.printStackTrace() );
}
}
}
Output
Message: 10
java.lang.ArrayIndexOutOfBoundsException: 10
at test.change(All.java:7)
at test.main(All.java:13)
Exceptions and Inheritance
The rule
A method that overrides another method may not be declared to throw more
checked exceptions than the overridden method
The Details
Let class Child be a subclass of class Parent
Let foo be a method of Parent that is overridden by child
If Child.foo has a throws clause that mentions any checked exceptions, then
Parent.foo must have a throws clause.
For every checked exception listed in Child.foo, that same exception class or
one of its superclasses must occur in the throws clause of Parent.foo
class Parent
{
public void foo() throws IOException {};
public void bar() {};
}
class Child extends Parent
{
public void foo() {}; // OK
public void bar() throws IOException{}; // Compile Error
}
class BoringLectureException extends Exception {
public BoringLectureException() {
super();
}
public BoringLectureException( String errorMessage ) {
super( errorMessage );
}
}
class NewExceptionTest {
public static void dullSpeaker() throws BoringLectureException {
// Code can go here
throw new BoringLectureException( "Change Topics" );
}
public static void main( String args[] ) {
try {
dullSpeaker();
} catch ( BoringLectureException e ) {
System.err.println( "Error: Time to " + e.getMessage() );
}
}
}
Output
Error: Time to Change Topics
1. Use exceptions for exceptional conditions, not simple tests
Good
Stack accountHistory;
if ( accountHistory.isEmpty() == false )
accountHistory.pop();
Not so Good
try
{
accountHistory.pop();
}
catch ( EmptyStackException doNothing )
{
}
A try for every line, and every line for a Try?
2. Don't Micro manage Exceptions
bad
try
{
amount = accountHistory.pop();
}
catch ( EmptyStackException doNothing )
{
amount = -1;
}
try
{
out.writeFloat( amount );
}
catch ( IOException ioError )
{
System.err.out( "problem writing to file" );
}
Better
try
{
amount = accountHistory.pop();
out.writeFloat( amount );
}
catch ( EmptyStackException doNothing )
{
}
catch ( IOException ioError )
{
System.err.out( "problem writing to file" );
}
Free Speech for Exceptions!
3. Don't Squelch Exceptions
Bad
try
{
amount = accountHistory.pop();
out.writeFloat( amount );
// a bunch more code that can throw various exceptions
}
catch ( Exception dontBotherMeWithExceptions )
{
}
4. Catch Exceptions
public static void main( String[] args ) throws Exception
{
// Lots of stuff here
}
AWTException | InstantiationException |
ArithmeticException | InterruptedException |
ArrayIndexOutOfBoundsException | InterruptedIOException |
ArrayStoreException | MalformedURLException |
ClassCastException | NegativeArraysizeException |
ClassNotFoundException | NoSuchElementException |
CloneNotSupportedException | NoSuchMethodException |
EOFException | NullPointerException |
EmptyStackException | NumberFormatException |
Exception | ProtocolException |
FileNotFoundException | RuntimeException |
IOException | SecurityException |
IllegalAccessException | SocketException |
IllegalArgumentException | StringIndexOutOfBoundsException |
IllegalMonitorStateException | UTFDataFormatException |
IllegalThreadStateException | UnknownHostException |
IndexOutOfBoundsException | UnknownServiceException |
Errors
AWTError | LinkageErrorNoClassDefFoundError |
AbstractMethodError | NoSuchFieldErrorNoSuchMethodError |
ClassCircularityError | OutOfMemoryError |
ClassFormatErrorError | StackOverflowError |
IllegalAccessError | UnknownError |
IncompatibleClassChangeError | UnsatisfiedLinkErrorVerifyError |
InstantiationErrorInternalError | VirtualMachineError |