Title: Exceptions and Assertions
1Exceptions and Assertions
2Exceptions
- Exceptions are unusual events detected by the
computer or software. - Not necessarily an error.
- Asynchronous exceptions can occur at any time,
independent of the program execution. - Example hardware error, user terminates
program - Synchronous exceptions occur in response to some
action by the program. - Example subscript out-of-bounds, read error
- Q Which type of exception can a program "catch",
if the language supports this feature?
3Types of Exceptions
- Hardware Errors such as write to write-protected
devices. - Hardware failures (memory error, etc) are usually
fatal and handled by hardware or OS, not
application programs. - Software Errors including access to invalid
memory address, attempt to access non-existent
file. - Language Violations (dynamic semantic errors)
such as illegal array subscript, referencing null
pointers. - User-defined (program-defined) conditions e.g.,
a parse-exception defined in a recursive-descent
program. Java and C allow user to define and
raise any "exception".
4Exceptions in Java
- Exceptions are objects from subclasses of
"Throwable".
Throwable
Error
Exception
IOException
RuntimeException
others
Detected and thrown by Java VM, such as
out-of-heap space
- IndexOutOfBounds
- NullPointer
- ClassCast (bad cast)
- many others (see API)
- EOFException
- ZipException
- many others
- ParseException
- user defined
- many others
5Example NullPointerException
public class LazyPerson private String
firstName private String lastName ... /
equals returns true if names are same / public
int equals(LazyPerson other) return
firstname.equals( other.firstName )
lastName.equals( other.lastName )
- NullPointerException
- if firstName or lastName is null!
- if other is null! (It could happen.)
6Example NullPointerException
public int fibonacci( int n ) // stupid code
-- you don't need an array here. // Array is
used just for exceptions example private long
fib fib0 1 fib1 1 for(int k2
kltn k) fibk fibk-1 fibk-2 return
fibn
- NullPointerException
- array reference fib was never assigned to an
array
7Example ArrayIndexOutOfBoundsException
public int fibonacci( int n ) // stupid code
-- you don't need an array here. // Array is
used just for exceptions example private long
fib new longn fib0 1 fib1
1 for(int k2 kltn k) fibk fibk-1
fibk-2 return fibn
- ArrayIndexOutOfBoundsException
- last element of array is fibn-1
- exception also occurs if a negative index is used
8Example ClassCastException
/ compare two students using Student ID /
public int compareTo( Object other ) // cast
"other" back to Student Student o (Student)
other return this.id.compareTo( o.id )
public static void main( String args )
Student joe new Student( "Joe","Nerd","475411
11" ) Dog dog new Dog( "Friendly"
) joe.compareTo( dog )
- ClassCastException
- occurs when a cast is used that doesn't match
object - exception also occurs if a negative index is used
9Avoiding ClassCastException
/ compare two students using Student ID /
public int cmpareTo( Object other ) if ( !
(other instanceof Student) ) return -1 // cast
"other" back to Student Student o (Student)
other return this.id.compareTo( other id )
public static void main( String args )
Student joe new Student("Joe","Nerd",
"47541111") Dog dog new Dog(
) joe.compareTo( dog )
- Better to throw your own exception here.
- What happens if other is null ?
10IOException, FileNotFoundException
/ open a file and read some data / public
void readFile( String filename ) // this could
throw FileNotFoundException FileInputStream in
new FileInputStream( filename ) // this could
throw IOException (read error) int c in.read(
)
- Better to throw your own exception here.
- What happens if other is null ?
11Knowing the Exceptions
- Read the Java API for the constructor and
methods. - IDE (Eclipse, NetBeans) will warn you of
exceptions you haven't "handled" (only for
CheckedException).
What exceptions could this scanner object
throw? Scanner input new Scanner( System.in
) int n input.nextInt( )
12Handling Exceptions
/ open a file and read some data / public
void readFile( String filename ) // this could
throw FileNotFoundException try
FileInputStream in new FileInputStream(
filename ) catch( FileNotFoundException e )
System.err.println("File not found
"filename) return
- called a try - catch block.
- Any exception thrown by code in the "try" block
will be directed to the matching "catch" block.
13Handling Exceptions scope problem
/ open a file and read some data / public
void readFile( String filename )
FileInputStream in // this could throw
FileNotFoundException try FileInputStream in
new FileInputStream( filename ) catch(
FileNotFoundException e ) System.err.println("
File not found "filename) return
- in previous slide, we can't use "in" outside of
the "try" block -- the block determines its
scope. - Solution define variable before the try block.
14Declaring Exceptions
- a method can declare that is may "throw" a type
of exception. - the exception is propagated up the call chain
- the caller must either "catch" or declare the
exception
/ open a file and read some data. _at_param
filename is file to read data from. _at_throws
FileNotFoundException if file doesn't exist /
public void readFile( String filename ) throws
FileNotFoundException // this could throw
FileNotFoundException FileInputStream in new
FileInputStream( filename )
15Checked Exceptions in Java
- Two categories of exceptions
- Checked Exceptions are exceptions that Java
requires the program to either handle or
explicitly acknowledge that it may generate this
exception. - Checked Exceptions include subclasses of
IOException, CloneNotSupportedException, and
user-defined classes that extend Exception. - The programmer declares that a method "throws" an
exception to a higher-level handler by writing - methodname(params) throws SomeException
- Example
- readFile(String filename) throws IOException
16Java "catch or declare" rule
- Any code that may generate a CheckedException
must either... - be explicitly handled ( try - catch block )
- or the method declares that it may throw the
exception -
don't need to declare FileNotFoundException
because it is subclass
readFile(String filename) throws IOException
...
17Guideline for exception handling
- The code should catch an exception if it can do
something about it. - if the caller can handle the exception better,
then let the caller handle it. - be as explicit as possible in declaring
exceptions -
/ BAD. What exception? / readFile(String
filename) throws Exception ... / Better.
/ readFile(String filename) throws
FileNotFoundException ...
18Unchecked Exceptions in Java
- Unchecked Exceptions the program may provide an
exception handler but it is not required. - Unchecked Exceptions include subclasses of Error
and RunTimeException. - Methods should not use "... throws SomeException"
for UncheckedExceptions. - Reason for having Unchecked Exceptions
- error conditions are beyond the control of the
application. You should let the JavaVM handle
them, or - it would be too cumbersome to require every
program to either "catch" or "throw" all
RunTimeExceptions. For example, every object
reference would require declaring or catching
"NullPointerException" !
19Example
- If you had to handle every NullPointerExceptions,
then the Java compiler would require
public String getReply( String prompt ) String
reply try // promptString could be
null System.out.print( prompt ) reply
console.next( ) // even though we test for
null, this statement // must still be inside a
try - catch block // for null pointer if (
reply ! null ) reply reply.trim().toLowerCa
se( ) catch (NullPointerException e) ...
return prompt
20Rule of Thumb for RunTimeException
- "If it is a RuntimeException, it's your fault!"
- -- Core Java, Volume 1, p. 560.
- An application should be able to prevent Runtime
exceptions by careful programming. - NullPointerException can be avoided by testing
for a null value before referencing a variable. - ArrayIndexOutOfBoundsException can be avoided by
correct programming (correct bounds on loops,
etc). - ClassCastException can be avoided by checking the
type of an object before casting it. This test is
idiomatic (standard) for compareTo( ) methods but
maybe omitted for efficiency. - ClassCastException often indicates faulty program
logic.
21Exception Handlers
- Syntax of an exception handler is
- try
- block-of-code ...
-
- catch (ExceptionType1 e) handler-code
- catch (ExceptionType2 e) handler-code ...
- finally code to always execute before
continuing
Stringbuffer buf new StringBuffer() try
while ( ( c System.in.read() ) ! 0
) buf.append(c) catch (IOException e)
System.out.println("I/O error "e)
22Multiple Exceptions
- In C and Java a "try" block can catch multiple
exceptions. - Exception handlers are tried in the order they
appear.
try System.in.read(buf) parseLine(buf)
catch (IOException e) System.out.println("I/
O exception "e) catch (Exception e)
System.out.println("Unknown exception "e)
catch (ParseException e) / This catch is
never reached! / System.out.println("Parse
exception "e)
23Nested Exception Handlers
- You may also nest try - catch blocks.
try try out new FileOutputStream("my
file") catch(FileNotFoundException e)
System.out.println("Error opening file")
throw e out.write(buf) catch
(IOException e) System.out.println("I/O
exception "e) catch (Exception e)
System.out.println("Unknown exception "e)
24Propagation of Exceptions
int A() ... throw new Exception("Help!")
int B() ... int result A( )
- Exception are propagated according to the path of
execution of a program. -
int test1() try answer B( )
catch(Exception e) ... int test2() try
answer B( ) catch(Exception e)
...
25Propagation of Exceptions (2)
- An exception is propagated to the first
dynamically scoped level that can "catch" the
exception.
int A(Object obj) Integer k (Integer)obj//
ClassCastException return k.IntValue() / B()
only catches IOException / int B(Object obj)
try result A(obj) catch (IOException
e) / do something / / C() catches any
RuntimeException / int C() try result
B("10") catch (RuntimeException e) ...
26Propagation of Exceptions (3)
- If the application program does not provide an
exception handler, then the default Java
exception handler is used. - The default exception handler
- prints name of exception and where it occurred
- prints stack trace
- terminates the program.
27Exceptions in C
- An exception can be any type!
- Exceptions can be programmer defined or
exceptions from the C standard library.
struct Error e try if ( n lt 0 ) throw
n else if ( n 0 ) throw "zero" else if ( n
1 ) throw e catch (int e1) cout ltlt
"integer exception raised" ltlt endl catch
(string e2) cout ltlt "string exception " ltlt
endl catch (Error e3) cout ltlt "struct
Error" ltlt endl
28Standard Exceptions in C
- C defines exception classes in ltexceptiongt.
- Hierarchy of classes
- exception (top level class)
- runtime_error
- logic_error
- others
- Exceptions can be thrown by C language
features - bad_alloc (thrown by "new")
- bad_cast (thrown by "dynamic_cast")
- bad_exception (generic exception)
29Exceptions in C
- Class Hierarchy include file
- exception ltexceptiongt
- bad_alloc ltnewgt
- bad_cast lttypeinfogt
- bad_exception ltexceptiongt
- bad_typeid lttypeinfogt
- failure ltiosgt
- logic_error (has subclasses) ltstdexceptgt
- runtime_error (has subclasses) ltstdexceptgt
- bad_exception is a generic type for unchecked
exceptions.
30Exception Handler in C
- Example catch failure of "new".
include ltiostreamgt using namespace std using
stdbad_alloc char makeArray(int nsize)
char p try p new charnsize
catch ( bad_alloc e ) cout ltlt "Couldn't
allocate array " cout ltlt e.what( ) ltlt
endl p null
31Declaring exceptions
- To declare that your function throws an exception
include ltiostreamgt using namespace std using
stdbad_alloc char makeArray(int nsize)
throw(bad_alloc) char p try p new
charnsize catch ( bad_alloc e ) cout ltlt
"Couldn't allocate array " cout ltlt e.what( )
ltlt endl throw // re-throw bad_alloc
exception
32Declaring no exceptions
- To declare that your function throws no
exceptions
include ltiostreamgt using namespace std using
stdbad_alloc char makeArray(int nsize)
throw() char p try p new
charnsize catch ( bad_alloc e ) cout ltlt
"Couldn't allocate array " cout ltlt e.what( )
ltlt endl return NULL
33Exception Handler in C
- A function can have multiple "catch" blocks.
int main( ) // ... other code goes here
... try sub() / sub() that throws
exceptions / catch ( bad_alloc e ) cerr
ltlt "Allocation error " ltlt e.what() catch (
exception e ) cerr ltlt "Exception " ltlt
e.what() catch ( ... ) // "..."
matches anything this catch // block catches
all other exceptions cerr ltlt "Unknown exception
" ltlt endl
34Rethrowing an Exception
- A function can throw an exception it has caught
int main( ) // ... other code goes here
... try sub() / sub() that throws
exceptions / catch ( bad_alloc e ) cerr
ltlt "Allocation error " ltlt e.what() throw
35C Default Exception Handler
- If an exception is not caught, C provides a
default exception handler - If the function didn't use "throw(something)" in
its header, then a method named terminate() is
called. - If a function declares exceptions in its header,
but throws some other exception, then the
function unexpected() is called. unexpected()
also calls terminate(). - unexpected() in implemented as a pointer. You
can change it to your own exception handler
using set_unexpected( your_function ) - Similarly, use set_terminate() to replace
terminate() with some other function. - Prototypes for set_unexpected() and
set_terminate() are defined in the header file
ltexceptiongt.
36C Default Exception Handler
include ltexceptiongt void my_terminator()
cerr ltlt "You're terminated!" ltlt endl exit(1)
void my_unexpected() cout ltlt "unexpected
exception thrown" ltlt endl exit(1) int
main() throw() set_unexpected(my_unexpected)
// ignore return value set_terminate(my_termina
tor) for(int i 1 i lt3 i) try f(i)
catch(some_exception e) cout ltlt
"main caught " ltlt e.what() ltlt endl throw
37Exception Handling is Expensive
- Runtime environment must locate first handler.
- Unwind call chain and stack
- locate return address of each stack frame and
jump to it. - invoke "prolog" code for each function
- branch to the exception handler
- Recommendation avoid exceptions in normal flow
of execution.
38Exception Handling is Expensive
- Example Java code to find a tree node matching
string
class Node String value Node left, right //
branches of this node // find a mode with
matching string value Node find(String s)
Node node int compare value.compareTo(s)
if (compare 0) return node try if
(compare gt 0) return left.find(s) if (compare
lt 0) return right.find(s) catch (
NullPointerException e ) return null
39Exception Handling is Expensive
- More efficient to rewrite code to avoid
exceptions
class Node String value Node left, right //
branches of this node // find a mode with
matching string value Node find(String s)
Node node int compare value.compareTo(s)
if (compare 0) return node if (compare gt
0 left ! null) return left.find(s) els
e if (compare lt 0 right ! null) return
right.find(s) else return null
40Exceptions Questions
- Do exception handlers use lexical or dynamic
scope? - What is the purpose of "finally" ?
- Efficiency see homework problem.
41Assertions
- Assertions are logical tests that should always
be true at a given point in a program. - Programmers use assertions to help verify program
correctness during development. - If an assertion is false, an exception is raised.
- After the program is completed, assertions can be
disabled using a compiler option, so they do not
effect "production" code -- but are still
available to the developer. - Both C and Java support assertions.
42Use of Assertions
- Assertions are used in methods to specify
- Pre-conditions conditions that should always be
true when the method is invoked - Post-conditions conditions that should be true
when the method returns - Example move a stack in Towers of Hanoi game.
void MoveStack(Stack fromStack, Stack
toStack) // stacks should not be null! assert
fromStack ! null "from is null" assert
toStack ! null "to is null" // fromStack
should not be empty assert fromStack.size() gt 0
"from empty" ... code goes here //
PostCondition toStack not empty assert
toStack.size() gt 0 "to is empty"
43"assert" versus throw AssertionError
- "assert" will throw an AssertionError. So
instead of "assert" - can we write this? is it equivalent?
// stacks should not be null! assert fromStack
! null "from is null"
// stacks should not be null! if ( fromStack
null ) throw new AssertionError("from is
null")
44"assert" in other languages
- how to emulate assertions in C
/ myheader.h / define DEBUG 1 / 0 for
production version /
include ltmyheader.hgt if DEBUG if ( fromStack
null ) fprintf(stderr, "fromStack is
null") endif
45multiple catch blocks
try / What is wrong with this code? / y
func(x) catch ( exception ) cerr ltlt "caught
exception" catch ( bad_alloc ) cerr ltlt
"caught bad_alloc" catch ( ... ) cerr ltlt
"what's this?" catch ( logic_error ) cerr ltlt
"Your Error!!"
try / What is wrong with this code?
/ System.in.read(buf) / throws IOException
/ catch ( Exception e ) / A
/ System.err.println("Exception "e) catch
( IOException e ) / B / System.err.println("I
O exception "e)