Download Chapter 14

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

Scala (programming language) wikipedia , lookup

Java (programming language) wikipedia , lookup

Java performance wikipedia , lookup

C syntax wikipedia , lookup

Covariance and contravariance (computer science) wikipedia , lookup

Java ConcurrentMap wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Class (computer programming) wikipedia , lookup

Go (programming language) wikipedia , lookup

Object-oriented programming wikipedia , lookup

Java syntax wikipedia , lookup

Name mangling wikipedia , lookup

Control flow wikipedia , lookup

Standard ML wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

C++ wikipedia , lookup

Structured programming wikipedia , lookup

C Sharp syntax wikipedia , lookup

Transcript
COMP 356
Programming Language Structures
Notes for Chapter 14 of Concepts of Programming Languages
Exception Handling
Exceptions:
• allow program units to signal error or other “exceptional” conditions
• allow error handling code to be separate from other code
• provide flexibility in where errors are handled
This is especially important for “library” units that may be reused in many programs, because different
client code will usually require errors to be handled in different ways.
Languages with exception handling typically include:
• a mechanism for signaling an exceptional condition (called raising or throwing an exception)
• a mechanism for detecting when an exception has been raised and taking some action in response
(called handling or catching an exception)
1
Exceptions in Java
Java has 2 kinds of exceptions:
• checked exceptions
– typically defined by the programmer
– methods must declare any checked exceptions that they could throw
• unchecked exceptions
– typically built-in, such as exceptions to indicate division by 0 or dereferencing of a null reference
– methods need not declare that they could throw unchecked exceptions (since almost all methods
could throw them)
1.1
Mechanics
• errors are signaled by throwing an exception (using keyword throw)
• any method whose body could throw a checked exception (that isn’t handled in the method itself)
must be declared with a throws clause containing a comma separated list of all exceptions that could
be thrown
• exceptions are handled using keywords try and catch surrounding a block that could throw an exception
Example (from class IntQueue):
public int dequeue() throws EmptyQueueException {
// return next queue element, or throw exception if queue is empty
int res = 0;
if (tail == null)
throw new EmptyQueueException("can’t dequeue empty queue");
else {
...
1
}
}
...
// code that calls dequeue
try {
System.out.println(iq.dequeue());
System.out.println(iq.isEmpty());
System.out.println(iq.dequeue());
} catch (EmptyQueueException e) {
System.out.println(e); // prints the string passed to the constructor
}
1.2
Defining Exceptions
In Java, exceptions are objects defined by exception classes:
• all exception classes must extend the system class Throwable (directly or indirectly)
• three system subclasses of Throwable that can be extended:
– Exception
– RuntimeException
– Error
• any exception class that extends Exception defines a checked exception
• other exception classes define unchecked exceptions
• system (built-in) exceptions extend RuntimeException or Error, and so are unchecked
• programmer-defined exceptions should almost always be checked exceptions (extend Exception):
– forces documentation that the exception could be thrown (in the throws clause of the method
declaration
– forces client code to explicitly deal with error conditions
Example - class EmptyQueueException:
public class EmptyQueueException extends Exception {
public EmptyQueueException(String mes) {
// invoke superclass constructor to set message for this instance
super(mes);
}
}
An exception is thrown by constructing an object of the appropriate exception class and using it with
keyword throw.
1.3
Handling Exceptions
A catch clause will handle objects of all subclasses of the class specified as its parameter. For example:
2
try {
..
} catch (Exception e) {
..
}
will catch all checked exceptions (which likely includes all programmer-defined exceptions), and so does not
differentiate exceptional conditions.
Better approach:
• declare an exception class for each kind of error
• handle exceptions using specific exception class parameters in the catch clauses.
General form:
try {
...
} catch (ExceptionSub1 e1) {
...
} catch (ExceptionSub2 e2) {
...
} catch (ExceptionSubn en) {
...
} finally {
...
}
where each ExceptionSubi is a different subclass of Exception. When an exception is thrown in the try
construct, the catch clauses are tried in order, and the first that matches the exception is used.
Hence, the following is bad and is rejected by the compiler:
class SuperException extends Exception { ... }
class SubException extends SuperException { ... }
...
try {
...
} catch (SuperException e1) {
...
} catch (SubException e2) {
...
}
because the second catch clause can never be used.
The code contained in the (optional) finally clause is executed whether an exception is thrown in the
try construct or not. This is useful for “cleanup” code (closing files, other freeing of resources, ...) that
must always be executed.
Binding of exceptions to handlers is both static and dynamic:
• static: if try constructs are nested, then the nearest enclosing catch clause (from the point where the
exception is thrown) that matches is used.
• dynamic: if the method that throws the exception does not have a handler for it, then the exception
travels up the method call chain (runtime stack) until the exception is caught or the chain is exhausted
(no more method invocations are active). Hence, any method calling another method that throws a
checked exception E must either catch E or throw E itself.
3
When an exception is caught, the code in the catch clause is executed, and then execution resumes
immediately after the last catch clause (or the finally clause if present) of the try construct. If an
exception is thrown but never caught, then the program terminates.
A catch clause can rethrow the exception that it caught (using keyword throw with no operand) or
create and throw a new exception. Such an exception will not be caught in the current try construct, so
there is no danger of creating a “loop”. This approach is useful when some local error handling is useful,
but more needs to be done at some other point in the program.
2
Exceptions in C++
Exceptions in C++ are very similar to those in Java, but there are some important differences.
Similarities:
• try constructs with catch clauses are used to handle exceptions
• the keyword throw is used to throw exceptions
• a catch clause can rethrow an exception (using throw with no operand) or throw a new exception
• binding of exceptions to handlers is identical to the Java case
Differences:
• values of any type (not just instances of exception classes) can be used as exceptions
• all exceptions are programmer-defined
• there is no distinction between checked and unchecked exceptions
• in Java, a method that overrides a superclass method can only throw exceptions that the overriden
method could throw. In C++, a member function overriding a superclass function can throw any
exception, regardless of those thrown by the overriden function.
Example:
int fun() {
...
if (error1()) throw 2;
...
if (error1()) throw 2.0;
...
}
...
try {
int i = fun();
} catch (int) {
// catches first exception, doesn’t observe value thrown
...
} catch (double d) {
// catches second exception, observes value thrown
...
} catch (...) {
// catches any exception not caught earlier
...
}
4
A catch clause that catches exceptions of type T will also catch exceptions of type const T, T& and
const T&. If T is a class type, then the catch clause will also catch exceptions of any subclass type.
A function can list the exception types that it throws using the keyword throw in the header. For
example:
int fun() throw (int, double) { ... }
This is similar to the use of throws in Java – if the header contains throw, then the function can only throw
the listed exceptions. However:
• in Java, a method with no throws clause in its header can not throw any checked exceptions
• in C++, a function with no throw clause in its header can throw any exception. A throw clause with
an empty list of exception types, i.e.:
int fun() throw () { ... }
indicates that the function can not throw any exceptions.
Final notes:
• many programmers prefer Java-style exception handling because it is:
– simpler
– more object-oriented
– easier to associate meaningful names with exception classes than with arbitrary types
• exceptions should only be used for conditions that are exceptional or unusual. Using them for expected
conditions such as end-of-file is inefficient and makes code difficult to read.
5