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
Exceptions
Chapter 9
Outcomes
Find the exception that crashed a program
find where it happened in your code
Understand how try-catch blocks work
Write a try-catch block to catch exceptions
your program might throw
Design and place try-catch blocks so your
program recovers gracefully
Exceptional Circumstances
Reading numbers from user
User types in a word
not the sort of thing we expected
program crashes
Enter a number: 20
Enter another number: done
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at SumNumbers.main(SumNumbers.java:26)
see SumNumbers.java
Exceptional Circumstances
Reading file name from user
User gives name of a file that doesn’t exist
can’t open that file for input
program crashes
Enter the name of a file and I will sum its numbers: noSuchFile.txt
Exception in thread "main" java.io.FileNotFoundException:
noSuchFile.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.util.Scanner.<init>(Scanner.java:636)
at SumUsersFile.main(SumUsersFile.java:20)
see SumUsersFile.java
Exceptions
Our Scanner has thrown an exception
Exception in thread “main”
java.util.InputMismatchException
Exception in thread “main”
java.io.FileNotFoundException
It ran into an error it couldn’t fix
program “crashed”
» eventually!
What Exception?
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at SumNumbers.main(SumNumbers.java:26)
Exception in thread "main" java.io.FileNotFoundException:
noSuchFile.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.util.Scanner.<init>(Scanner.java:636)
at SumUsersFile.main(SumUsersFile.java:20)
Where?
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at SumNumbers.main(SumNumbers.java:26)
Exception in thread "main" java.io.FileNotFoundException:
noSuchFile.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.util.Scanner.<init>(Scanner.java:636)
at SumUsersFile.main(SumUsersFile.java:20)
Where???
Methods call other methods
which may call other methods in turn
One method throws the exception
error message shows whole “stack” of calls
main
nextDouble
Exception in thread "main" java.util.InputMismatchException
next
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at SumNumbers.main(SumNumbers.java:26)
throwFor
Look for Your Program
Many of the methods don’t belong to you
you can’t do anything about them
Some of the methods are yours
that’s where you can do something
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextDouble(Scanner.java:2387)
at SumNumbers.main(SumNumbers.java:26)
» line 26 of SumNumbers.java
Exercise
Where did this exception get thrown from?
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at java.util.Scanner.nextInt(Scanner.java:2050)
at csci1227.Scanner.nextInt(Scanner.java:169)
at ArraySearcher.search(ArraySearcher.java:178)
at ArraySearcher.main(ArraySearcher.java:58)
What methods were called?
What line(s) of your program are relevant?
Catching Exceptions
try-catch block
try {
…
// code that may throw an exception
} catch(ExceptionClass exceptionObject) {
…
// code to handle the exception
}
Try to do this, and if something goes wrong,
do this to deal with it
Caught or Declared?
Exceptions must be caught or declared
try-catch exception is caught
throws exception is declared
Don’t catch them need to declare them
Catch them don’t declare them
take the “throws” clause(s) away
Only some exceptions need to be caught or declared.
FileNotFoundException needs to be caught or declared.
Others we look at today don’t need to be caught or declared,
but we’ll catch them anyway – to make our programs nicer.
Catching Exceptions
For catching InputMismatchException
inside the number-reading loop
try {
num = kbd.nextDouble();
// may throw an exception
kbd.nextLine();
}
catch(InputMismatchException ime) {
System.out.println(“That’s not a number!”);
break; // exit from loop
Note: it’s a parameter!
}
see CatchInputMismatch.java
When No Exceptions Occur
while (num >= 0.0) {
sum += num;
System.out.print(“Enter another number: ”);
try {
num = kbd.nextDouble();
kbd.nextLine();
}
catch(InputMismatchException e) {
System.out.println(“That’s not a number!”);
break; // exit from loop
}
}
When An Exception Occurs
while (num >= 0.0) {
sum += num;
System.out.print(“Enter another number: ”);
try {
num = kbd.nextDouble(); // doesn’t even get to finish!
kbd.nextLine();
}
catch(InputMismatchException e) {
System.out.println(“That’s not a number!”);
break; // exit from loop
}
}
Notes
InputMismatchException part of java.util
needs to be imported along with Scanner
import java.util.Scanner;
import java.util.InputMismatchException;
Our program exits the loop because of the
break command
normally would continue on inside the loop
(or whatever comes after the catch block)
When an Exception Occurs…
Code in try block gets skipped
right out from where the exception occurred
// read an integer and save it in num
num = kbd.nextInt();
// skip the rest of the input line
kbd.nextLine();
if next thing isn’t an int, NONE of that happens
» doesn’t read an integer (no integer there to be read!)
» doesn’t save anything in num (num unchanged!)
» doesn’t skip rest of line
Dealing with Exceptions
After catching the exception, the body of
the catch block is executed
does whatever it says to do
» print a message; break out of a loop
Question to ask yourself:
What do I want my program to do when it
catches this exception?
What Do I Want to Do?
Reading int values; non-int value entered
try { num = kbd.nextInt(); }
catch (InputMismatchException ime) {
» end the loop?
break;
» skip invalid data?
kbd.next();
}
but if you skip, what else might go wrong?
Exercise
What happens with the following code
when the user enters a non-number?
while (num >= 0.0) {
sum += num;
System.out.print(“Enter another number: ”);
try {
num = kbd.nextDouble();
kbd.nextLine();
}
catch(InputMismatchException e) {
System.out.println(“That’s not a number!”); kbd.nextLine();
}
}
What goes wrong?
How might we fix it?
Bigger Try Blocks
Enter a word instead of the first number
program crashes!
Catch blocks only catch exceptions from the
corresponding try blocks
exceptions from outside don’t get caught
Try block can be as big as you want
so long as it stays inside the method
A Loop inside a try Block
Exception stop reading numbers
even if it’s the first number!
int sum = 0;
try {
int num = kbd.nextInt();
while (num >= 0) {
sum += num;
num = kbd.nextInt();
}
}
catch (InputMismatchException ime) {}
System.out.println(“The sum is ” + sum);
What does the catch block do here?
Exercise
Revise the code so that the sum is only
printed if the loop ends “normally”
that is, by the user entering a negative number
int sum = 0;
try {
int num = kbd.nextInt();
while (num >= 0) {
sum += num;
num = kbd.nextInt();
}
}
catch (InputMismatchException ime) {}
System.out.println(“The sum is ” + sum);
NOTE: You don’t need to add any code. Just move a piece of it!
File Not Found Exceptions
In file i/o we have FileNotFoundExceptions
generated when try to create a Scanner
» or a PrintWriter
What do we want to happen?
end the program (gracefully!)
give user another chance
» maybe after 3 chances end the program
use a default file or value
End the Program
Catch block should also print error message
try {
System.out.print(“Enter file name: ”);
Scanner fin = new Scanner(new File(fileName));
// read from the file using fin here
fin.close();
}
catch (FileNotFoundException fnf) {
System.err.println(“File not found. Quitting.”);
System.exit(1);
Error message (just before System.exit) should
}
be printed to System.err instead of System.out.
System.exit
End the program
takes one argument: program return code
System.exit(0) everything finished fine
System.exit(1) something went wrong
System.exit(2) something (else) went wrong
System.exit(3) something (else else) ...
Usually only need (0) and (1)
otherwise NAME your return codes (final vars)
Exercise
Revise this code to exit program if the file
SecretPlanet.txt can’t be found
public Planet ReadPlanetFromFile()
throws FileNotFoundException {
Scanner fin = new Scanner(new File(“SecretPlanet.txt”));
String aName = fin.nextLine();
int aCode = fin.nextInt();
double aDist = fin.nextDouble();
fin.close();
return new Planet(aName, aDist, aCode);
}
Give User Another Chance
Print warning message and try again
need a loop with try-catch block inside it
Scanner fin = null;
while (fin == null) {
try {
System.out.print(“Enter file name: ”);
String name = kbd.nextLine();
fin = new Scanner(new File(name));
} catch (FileNotFoundException fnf) {
System.out.println(“Not found! Try again.”);
}
}
// read from the file using fin down here
Scanner Declared Outside Loop
We will need the Scanner fin after the loop
declare it before the loop use it after
» declare in loop can’t use it after
» same applies to try block!
initialize fin to null
» means there is no Scanner here
create new Scanner inside loop
» assign to fin
» if it works, fin will not be null (loop ends)
» if it doesn’t, fin will still be null (loop will continue)
Give Three Chances
Use a count-controlled loop + break
Scanner fin = null;
for (int i = 0; i < 3; i++) {
try {
System.out.print(“Enter file name: ”);
fin = new Scanner(new File(kbd.nextLine()));
break;
// exit from the loop
} catch (FileNotFoundException fnf) {
System.out.println(“Can’t find that file!”);
}
}
if (fin == null) {System.exit(1);} // add error msg
// read from the file using fin down here
Count Control + break
For loop user gets only 3 chances
try-catch in case user gives bad file name
» error message printed and loop continues
if no exception continues in try-block body
» break command loop ends
(even if user hasn’t taken all three chances)
Need to check after loop if fin is still null
user took three chances, but no good file given
» print error message and exit program
Use a Default File
If user’s named file doesn’t exist, use a
name hard-coded into the program
Scanner fin = null;
try {
System.out.print(“Enter file name: ”);
fin = new Scanner(new File(kbd.nextLine()));
} catch (FileNotFoundException fnf) {
fin = new Scanner(new File(“DefaultData.txt”));
}
// read from the file using fin down here
But What if That Doesn’t Work?
If can’t open default file, program will crash
it’s not in a try block!
» So add the try block! it’s just fine!
Scanner fin = null;
try {
System.out.print(“Enter file name: ”);
fin = new Scanner(new File(kbd.nextLine()));
} catch (FileNotFoundException fnf) {
try {
fin = new Scanner(new File(“DefaultData.txt”));
} catch(FileNotFoundException fnf) {
System.exit(1); // add error message!
}
}
Exercise
Revise this code to return Earth (code = 0
and distance = 149.6) if file not found
» don’t open a different file; return a different Planet!
public Planet ReadPlanetFromFile()
throws FileNotFoundException {
Scanner fin = new Scanner(new File(“SecretPlanet.txt”));
String aName = fin.nextLine();
int aCode = fin.nextInt();
double aDist = fin.nextDouble();
fin.close();
return new Planet(aName, aDist, aCode);
}
No Such Element Exception
Try to read from a file with no more data
what if 3Nums.txt only had two numbers in it?
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:838)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at java.util.Scanner.nextInt(Scanner.java:2050)
at Sum3B_FromFile.main(Sum3B_FromFile.java:24)
not the same as an InputMismatchException
but either one could happen
Catching Different Exceptions
More than one thing could go wrong
some files have invalid data (input mismatch)
some files have missing data (no such element)
Want one program to deal with either error
work normally for complete and correct files
recover from error in files with invalid data
recover from error in files with missing data
one try; two catches
Catching Different Exceptions
Can have more than one catch block
each has a different exception it catches
try { … }
catch(InputMismatchException ime) {…}
catch(NoSuchElementException nse) {…}
if an exception is thrown, it goes to the
matching catch block
if no matching block, it keeps going
» until it is caught, or until it gets out the top (crash!)
see WeeklyTemps.java
Catching Different Exceptions
try {
for (int i = 0; i < temps.length; i++) {
temps[i] = in.nextDouble();
sum += temps[i];
}
// code to process temperatures hidden
} catch (InputMismatchException ime) {
System.err.println(fileName + " has bad data.");
System.exit(ERR_CORRUPT);
} catch (NoSuchElementException nse) {
System.err.println(fileName + " missing data.");
System.exit(ERR_MISSING_DATA);
}
see WeeklyTemps.java
try with Multiple catches
Can have as many catch blocks as you need
one for each kind of error that might happen
» WeeklyTemps.java has three catches on one try
try { … }
catch (FileNotFoundException fnf) { … }
catch (InputMismatchException ime) { … }
catch (NoSuchElementException nse) { …}
but each error must be able to happen in that try
» even if it’s on different lines
Multiple try-catch Blocks
Can have as many try blocks as you need in
any program (or method)
each one needs at least one catch block
Can go anywhere other controls can go
(even inside other try or catch blocks)
Other controls can go inside them
inside the try; inside the catch
Catching Some, Throwing Others
Some exceptions “must be declared or
caught to be thrown”
file not found exception, for example
either catch(FNFE fnf) or throws FNFE
Other exceptions don’t
input mismatch, no such element, index out of
bounds, array index out of bounds, …
but you can catch them if you want
Note: In my notes, FNFE is short for FileNotFoundException.
In your code you have to write it out in full!
Catching Some, Throwing Others
Don’t have to catch exceptions in the same
method where they arrive in the program
for example, main calls doThis
doThis does something that might go wrong
doThis does not cacth the exception
» it’s declared to throw a file not found exception, an
input mismatch exception, or whatever
main catches that exception
main has the try-catch blocks
Catching Some, Throwing Others
SumManyFiles program sums lots of files
repeats until user enters a non-existent file
Has a method (sumThisFile) to do file i/o
catches InputMismatchException
» skips non-numeric input while summing numbers
declares FileNotFoundException
main catches the FileNotFoundException
catches it outside the loop for summing files
» loop ends!
see SumManyFiles.java
SumManyFiles.java (part 1)
See the full program on-line
public static void main(String[] args) {
try {
while (true) {
// deliberately infinite loop!
System.out.print("Enter file name: ");
name = kbd.nextLine();
sum = sumThisFile(name);
// throws FNFE
System.out.println("The sum of all the numbers in "
+ name + " is " + sum + ".\n");
}
} catch (FileNotFoundException fnf) {}
}
SumManyFiles.java (part 2)
See the full program on-line
public static double sumThisFile(String name)
throws FileNotFoundException {
Scanner fin = new Scanner(new File(name)); // throws FNFE
double sum = 0.0;
while (fin.hasNext()) {
try { double num = fin.nextDouble(); sum += num; }
catch (InputMismatchException ime) { fin.next(); }
}
return sum;
}
One Issue
Multiple catch blocks with one try block,
the order of the catches might be important!
NetBeans will let you know!
} catch (NoSuchElementException nse) {
// error handler code hidden
} catch (InputMismatchException ime) {
// error handler code missing
exception InputMismatchException has
already been caught
just move the offending exception earlier
I’ll explain why this is next week.
It’s got to do with inheritance.
Questions?