1
|
- Announcements
- hw9 due tonight
- hw9 due Thursday, April 22
- exam Tuesday, April 27
- Agenda
- Questions
- Error handling (continued)
|
2
|
- Java’s object oriented mechanism for error handling
- more powerful, more flexible than using return
- Java keywords try, catch, throw,throws
- in class: banking system, Juno with Exceptions
- for hw: improve Exception handling in Juno 7.5
- Model
- in client: instead of testing a returned value
- try, hoping for the best
- prepare to pick up the pieces if necessary (catch)
- in code where the error may occur:
- detect error
- create a new Exception and throw it
|
3
|
- Suppose a customer tries to withdraw more than is in her account.
- Eventually BankAccount.java line 143 executes:
- if (newBalance < 0) { throw new InsufficientFundsException …
- Read code backward looking for messages (method invocations) to trace
methods that are active at that moment in order to see where that
Exception is caught
|
4
|
- method
class
line
- incrementBalance BA.java 144
- withdraw BA.java 77
- processTrans… Bank.java 173
- visit Bank.java 96
- main Bank.java 450
|
5
|
- At any moment while a program is running you can trace the sequence of
active methods from the currently executing statement back to main()
- That sequence is the method invocation stack
- It’s called the call stack in C - often in Java too (because it’s easier
to say)
- The call stack is dynamic, changing as the program runs (the program
itself is static - fixed at compile time)
- There will be a call stack question on the exam
|
6
|
- The call stack
- grows each time a message invokes a method
- shrinks each time a method returns
- main() is always the first thing pushed on to the stack and the last to
pop off: when main is done the program is done
- In CS a stack is a last in first out collection
- push adds an item to the stack
- pop removes one
- The call stack
- push a method when it’s invoked
- pop a method when it returns
|
7
|
- When error detected (BA.java line 143):
- if (newBalance < 0) throw new
InsufficientFundsException …
- Normal flow control stops - JVM looks for the nearest catch, which may
be
- in the running method
- somewhere up the call stack
|
8
|
- incrementBalance throws an InsufficientFundsException and does not catch
it (no try block here)
- The incrementBalance message was sent from BankAccount withdraw method,
which doesn’t catch the Exception either (no try block)
- The withdraw message was sent from Bank processTransactionsForAccount
method – inside a try block. So control transfers to the matching catch
block, which handles the Exception
|
9
|
- private final void incrementBalance( int amount )
- throws
InsufficientFundsException
- {
- if ( . . . ) {
- throw new InsufficientFundsException();
- }
- }
- Since incrementBalance might throw an InsufficientFundsException and (if
it does) it does not catch it, it must declare its intention to throw it
on up the stack to its caller by asserting throws
InsufficientFUndsException
- throws means might throw, not does throw
|
10
|
- public int withdraw( int amount )
- throws
InsufficientFundsException
- {
- incrementBalance( -amount );
- }
- Since withdraw might see an InsufficientFundsException thrown by
incrementBalance it must either
- catch it // it doesn’t
- or declare its intention to throw it on up the stack to its caller by
asserting
throws InsufficientFUndsException
|
11
|
- No throws cause needed for these, but you can catch them if you suspect
one may be thrown
- NoSuchElementException
- thrown for you by JVM when you try to ask for a element after an
Iterator is done
- NullPointerException
- thrown for you by JVM when you try to send a message to an Object that
does not exist
- ClassCastException
- thrown for you by JVM when you try to cast an Object to a type it isn’t
an instance of
- ArrayIndexOutOfBoundsException …
|
12
|
- JunoExceptions are caught in the try/catch in CLIShell interpret lines
73-89
- Note how different kinds of Exceptions are dealt with in order
- ExitShellException is thrown (only) by doIt in LogoutCommand class
- BadShellCommandException knows what command was bad so we can give help
- Catch a generic JunoException and print its message
- Then deal with truly unexpected errors … catch any Exception. At least
Juno won’t crash.
|
13
|
- Errors detected in the various doIt methods
- doIt declaration in abstract ShellCommand class says that it throws
JunoException
- Example: TypeCommand.java, where
we have written all the error detection
|
14
|
- try {
- filename = args.nextToken();
- }
- catch (NoSuchElementException e)
{
- throw
- new BadShellCommandException(
this );
- }
- Catch JVM’s Exception and throw one of your own that makes more sense in
this application
|
15
|
- try {
- // retrieve foo from current
directory
- // cast to TextFile and print
contents
- }
- catch (NullPointerException e) {
- // throw a JunoException
- }
- catch (ClassCastException e) {
- // throw a JunoException
- }
|
16
|
- At any moment while a program is running you can trace the sequence of
active methods from the currently executing statement back to main()
- That sequence is the method invocation stack
- It’s called the call stack in C - often in Java too
- When a method throws an Exception the JVM looks for a surrounding try
block so it can resume execution in the corresponding catch
- The search begins locally and works its way back through the call stack
|
17
|
- method
class next call on
line
- doIt TypeCommand
- interpret Shell 74
- CLIShell Shell 50
- constructor Shell 41
- interpret LoginInterpreter 89
- CLILogin LoginInterpreter 60
- constructor Juno 66
- main Juno 190
|
18
|
- public void doIt( ... )
- throws JunoException
- {
- ...
- }
- Since doIt might throw a JunoException it must
- catch it // it doesn’t
- or declare its intention to throw it on up the stack to its caller by
asserting throws JunoException
- throws means might throw, not does throw
- Built in Exceptions don’t need a throws clause
- If uncaught they crash the program
|
19
|
- Exception examples in a short standalone program
- The fairy tale: guess my name
- examples/RumpelStiltskin.java
- > Java RumpelStiltskin
- > Java RumpelStiltskin foo
- > Java RumpelStiltskin foo bar
- > Java RumpelStiltskin RumpelStiltskin
|
20
|
- Design (pseudocode)
- If there is no command line argument
- print usage message
- end the program
- Two possible implementation strategies
- test for args[0], proceed based on test result
- assume args[0] is there, catch Exception if not
|
21
|
- if (args.length == 0 ) {
- System.out.println(
- "usage: java
RumpelStiltskin guess");
- System.exit(0); // leave program gracefully
- }
- // continue normal processing
|
22
|
- try {
- System.out.println(”Are you
" + args[0] +'?');
- rumpelstiltskin.guessName(args[0]);
- System.out.println("Yes! How
did you guess?");
- System.exit(0); // leave program
gracefully
- }
- // come here right away if there is no args[0]
- catch (IndexOutOfBoundsException e) {
- System.out.println(
- "usage: java
RumpelStiltskin guess");
- System.exit(0); // leave program gracefully
- }
|
23
|
- sorry - foo is not my name
- Intentionally generate a NullPointerException,
- see what the Exception's toString method returns
- java.lang.NullPointerException
- Experiment with the printStackTrace() method:
- BadGuessException
- at
java.lang.Throwable.<init>(Compiled Code)
- at
java.lang.Exception.<init>(Compiled Code)
- at
BadGuessException.<init>(Compiled Code)
- at
Wizard.guessName(Compiled Code)
- at
Wizard.makeMischief(Compiled Code)
- at
RumpelStiltskin.main(Compiled Code)
- Look for a second command line argument,
- see what happens if it's not there:
- java.lang.ArrayIndexOutOfBoundsException: 1
- at
RumpelStiltskin.main(Compiled Code)
|
24
|
- Add error handling to register and login
- Error detection for all shell commands
- Count fraction of Juno that’s there for error handling
|