Exceptions, Strings, IO

advertisement
CS 340
1
DATA STRUCTURES
Lecture: Exceptions, IO
Slides adapted from Prof. Steven Roehrig
CS 340
2
Today’s Topics
• Older, and more modern, strategies for error handling.
• Exception handling basics.
• Some exception details:
• plain Exceptions vs. RuntimeExceptions
• Exceptions containing information
• Exception hierarchies
• What’s really practical using exceptions.
CS 340
3
Exception Handling
• The compiler is supposed to report syntax errors,
it but can’t discover many other types of errors:
• casts to the wrong type
• files that don’t exist
• dividing by zero
• indexing out of bounds
• incorrect data formats
• badly formed SQL queries
• etc. etc.
• Unresolved, many of these errors prevent a
program from continuing correctly.
CS 340
4
Exception Handling
• We would like to be aware of these “exceptional”
situations, in hopes of
• recovery
• retrying
• trying an alternate strategy
• cleanup before exit
• or, just finding out where the problem is!
• Nothing is more mystifying than a program that just “goes
up in smoke”!
CS 340
5
Strategies for Error Handling
• In the course of programming, we constantly test
for situations that routinely arise.
• We include logic to deal with the possibilities
(switch, if-else, etc.).
• “Exceptional” situations are different. They are
things that “should never happen”.
• We expect our code will be free from bugs, but…
• We’re usually wrong.
CS 340
6
Strategies for Error Handling
• Pre-testing the arguments to each function call.
• Checking return values indicating error.
• Setting and checking global error variables.
• These are not formal methods, not part of the
programming language itself.
• They require programmer discipline (but so does the use
of exceptions…).
CS 340
7
Example
void workOnArray(double[] myArray, int otherInfo) {
int i = 0;
// complicated calculation of array index i, using otherInfo
myArray[i] = 3.14159;
// what if i is out of bounds?
}
CS 340
8
Example (cont.)
int workOnArray(double[] myArray, int otherInfo) {
int i = 0;
// complicated calculation of array index i, using otherInfo
if (i >= 0 && i < myArray.length) {
myArray[i] = 3.14159;
return 0; // indicating everything OK
}
else
return -1; // indicating an error
}
CS 340
9
Potential Problem
• What if workOnArray() needs to return a value (say, a
double)?
• The “C” approach: values are returned through additional
reference arguments in the method – not directly in Java.
• This quickly gets cumbersome.
CS 340
10
Another Technique: Globals
• There are no true global variables in Java, but we “fake it”
all the time.
• Write a class with static variables!
• These are effectively available anywhere in a program,
and could be used to signal error conditions.
CS 340
11
Faking A Global Variable
public class MyGlobal {
public static int indexError;
MyGlobal() { } // indexError automatically initialized to 0
}
void workOnArray(double[] myArray, int otherInfo) {
int i = 0;
// complicated calculation of array index i, using otherInfo
if (i >= 0 && i < myArray.length) {
myArray[i] = 3.14159;
}
else
MyGlobal.indexError = -1;
}
CS 340
12
Three Important Issues
• Where should the tests be done?
• Before the array is “indexed into”?
• By the array class itself?
• Where should the error be reported?
• Locally, or “further down” in the call stack?
• Stroustrup says that authors of libraries can’t know their
user’s contexts, so can’t know what to do.
• Who is responsible for adjudicating the error?
• Exception handling in Java helps with these
problems, but doesn’t completely solve them.
CS 340
13
Example
class MyException extends Exception {
MyException(String message) {
super(message);
}
}
class MyExceptionThrower {
void f() throws MyException {
throw new MyException("Throwing MyException");
}
}
CS 340
14
Example, cont
public static void main(String[] args){
MyExceptionThrower t = new MyExceptionThrower();
try {
t.f();
}
catch (MyException e) {
e.printStackTrace();
}
finally {
System.out.println("Done");
}
}
CS 340
15
Some Points
• f() must have “throws MyException”. Otherwise,
compiler will complain.
• The compiler insists any call to this method be
“tested” by enclosing it in a try block, or else we
get an “unreported exception” error.
• If we do include a try block , there has to be a
corresponding catch block or finally clause.
• When an exception is thrown, control goes to the
matching catch block.
CS 340
16
More Points
• All of this is true because our exception extended the
Exception class.
• If we extend RuntimeException instead, we don’t need
to say throws, nor include try and catch blocks.
• RuntimeExceptions are special; the Java runtime system
takes care of them automatically.
CS 340
Exceptions Always Get Caught
public class NeverCaught {
static void g() {
throw new RuntimeException(“From g()”);
}
static void f() {
g();
}
public static void main(String[] args) {
f();
}
}
17
CS 340
18
“Uncaught” Exceptions
• If an exception makes it all the way “back” to
main() without being caught, the Java runtime
system calls printStackTrace() and exits the
program:
java.lang.RuntimeException: From g()
at NeverCaught.f(NeverCaught.java:5)
at NeverCaught.g(NeverCaught.java:8)
at NeverCaught.main(NeverCaught.java:11)
Exception in thread "main"
• You can call printStackTrace() yourself if you
want (and it’s useful to do it).
19
CS 340
Call Stack, Normal Execution
main() called
f() called
g() called
f()
main()
main()
time
g()
f()
main()
g() finished
f()
main()
f() finished
main()
20
CS 340
Call Stack, With Exception
main() called
f() called
g() called
main()
f()
main()
search f() for
handler, exit f()
g()
f()
main()
exception thrown,
g() has no handler,
exit g()
f()
main()
main()
search main() for
handler, call
printStackTrace(),
exit main()
CS 340
21
Catching Any Exception
• We are always interested in exceptions that implement
the interface Exception.
• So, a catch block like
catch(Exception e) {
System.out.println(“Caught an exception”);
}
will catch any exception.
• If you have multiple catch blocks, this one should be last.
CS 340
22
Multiple Catch Blocks
• There may be several possible errors generated by a
block of code:
try {
// try this
// and this
}
catch(YourException e) {
System.out.println(“Caught exception defined by you”);
}
catch(Exception e) {
System.out.println(“Caught some other exception”);
}
CS 340
23
Rethrowing an Exception
• Suppose you’ve caught an exception, and
decided you can’t recover from it, but perhaps a
higher context can.
• You can rethrow it:
catch(Exception e) {
System.out.println(“An exception was caught”);
throw e;
}
• The stack trace remains unchanged if it is
caught higher up.
CS 340
Catching, Fixing and Retrying
public class Retry {
static int i = 0;
public void f() {
try { g(); }
catch(Exception e) {
System.out.println("Caught exception, i = " + i);
i++;
f();
}
}
void g() throws gException {
if (i < 3) { throw new gException(); }
else
System.out.println("g() is working now");
}
24
CS 340
25
This Can Be Dangerous
public class Retry {
int i = 0;
boolean fileIsOpen = false;
public void f() {
try {
if (fileIsOpen)
System.out.println("Opening an already opened file!");
else
fileIsOpen = true; // i.e., open the file
g();
fileIsOpen = false; // i.e., close the file
}
// file will be left open: Dangerous!
CS 340
26
What’s So Dangerous?
• Just close the file in the catch block? Good idea! But,
what if some other exception were thrown, one that you
didn’t catch?
catch(gException e) {
System.out.println("Caught exception, i = " + i);
i++;
fileIsOpen = false;
f();
}
finally {
fileIsOpen = false;
}
CS 340
27
Exception Hierarchies
• Exceptions are classes, so can be in inheritance
hierarchies.
• The usual polymorphism rules apply.
• A handler for a superclass exception will catch a
subclass exception.
• This makes it easy to catch groups of exceptions.
• Exceptions are real objects (created with new),
and so can have constructors and data members.
CS 340
Termination Vs. Resumption
• Java makes it hard to complete this cycle:
• find a problem,
• throw an exception,
• fix the problem in the handler, and
• go back to where you left off.
• This is called “resumption”.
• Java assumes you don’t want to go back.
• This is called “termination”.
28
CS 340
29
What You Can Do
• Fix the problem and call the method that caused
the exception once more.
• “Patch things up” and continue without retrying
the method.
• Calculate some alternative result.
• Do what you can in the current context, and
rethrow the same exception to a higher context.
• Do what you can, and throw a different exception
to a higher context.
• Terminate the program (how?).
CS 340
Java vs C#
Program Structure
Operators
Choices
Loops
30
CS 340
31
Java vs C#: Exception Handling
Java
C#
// Must be in a method that is declared to
throw this exception
Exception ex = new Exception("Something is
really wrong.");
throw ex;
Exception up = new Exception("Something
is really wrong.");
throw up; // ha ha
try {
y = 0;
x = 10 / y;
} catch (Exception ex) {
System.out.println(ex.getMessage());
} finally {
// Code that always gets executed
}
try {
y = 0;
x = 10 / y;
} catch (Exception ex) {
// Variable
"ex" is optional
Console.WriteLine(ex.Message);
} finally {
// Code that always gets executed
}
CS 340
32
Java vs C#: Strings
Java
C#
// My birthday: Oct 12, 1973
java.util.Calendar c = new
java.util.GregorianCalendar(1973, 10, 12);
String s = String.format("My birthday: %1$tb
%1$te, %1$tY", c);
// My birthday: Oct 12, 1973
DateTime dt = new DateTime(1973, 10,
12);
// Mutable string
StringBuffer buffer = new StringBuffer("two
");
buffer.append("three ");
buffer.insert(0, "one ");
buffer.replace(4, 7, "TWO");
System.out.println(buffer); // Prints "one
TWO three"
string s = "My birthday: " +
dt.ToString("MMM dd, yyyy");
// Mutable string
System.Text.StringBuilder buffer = new
System.Text.StringBuilder("two ");
buffer.Append("three ");
buffer.Insert(0, "one ");
buffer.Replace("two", "TWO");
Console.WriteLine(buffer); // Prints "one
TWO three"
CS 340
33
Java vs C#: Console I/O
Java
java.io.DataInput in = new
java.io.DataInputStream(System.in);
System.out.print("What is your name? ");
String name = in.readLine();
System.out.print("How old are you? ");
int age = Integer.parseInt(in.readLine());
System.out.println(name + " is " + age + "
years old.");
C#
Console.Write("What's your name? ");
string name = Console.ReadLine();
Console.Write("How old are you? ");
int age =
Convert.ToInt32(Console.ReadLine());
Console.WriteLine(name + " is " + age + "
years old.");
int c = System.in.read(); // Read single
char
System.out.println(c);
// Prints 65 if user
enters "A"
int c = Console.Read(); // Read single char
Console.WriteLine(c); // Prints 65 if user
enters "A"
// The studio costs $499.00 for 3 months.
System.out.printf("The %s costs $%.2f for
%d months.%n", "studio", 499.0, 3);
// The studio costs $499.00 for 3 months.
Console.WriteLine("The {0} costs {1:C} for
{2} months.\n", "studio", 499.0, 3);
// Today is 06/25/04
System.out.printf("Today is %tD\n", new
java.util.Date());
// Today is 06/25/2004
Console.WriteLine("Today is " +
DateTime.Now.ToShortDateString());
CS 340
Java vs C#: File I/O
Java
C#
import java.io.*;
using System.IO;
// Character stream writing
FileWriter writer = new
FileWriter("c:\\myfile.txt");
// Character stream writing
StreamWriter writer =
File.CreateText("c:\\myfile.txt");
writer.WriteLine("Out to file.");
writer.Close();
writer.write("Out to file.\n");
writer.close();
// Character stream reading
FileReader reader = new
FileReader("c:\\myfile.txt");
BufferedReader br = new
BufferedReader(reader);
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
reader.close();
// Character stream reading
StreamReader reader =
File.OpenText("c:\\myfile.txt");
string line = reader.ReadLine();
while (line != null) {
Console.WriteLine(line);
line = reader.ReadLine();
}
reader.Close();
34
Download