Download 2016-06-Exceptions

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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?